36 MInt i, ia, ir, j, l, mid;
43 if(ir == l + 1 && arr[indx[ir]] < arr[indx[l]])
SWAP(indx[l], indx[ir]);
47 SWAP(indx[mid], indx[l + 1]);
48 if(arr[indx[l]] > arr[indx[ir]])
SWAP(indx[l], indx[ir]);
49 if(arr[indx[l + 1]] > arr[indx[ir]])
SWAP(indx[l + 1], indx[ir]);
50 if(arr[indx[l]] > arr[indx[l + 1]])
SWAP(indx[l], indx[l + 1]);
58 while(arr[indx[i]] <
a);
61 while(arr[indx[j]] >
a);
63 SWAP(indx[i], indx[j]);
65 indx[l + 1] = indx[j];
67 if(j >= k) ir = j - 1;
77 std::vector<Point<DIM>>
ptss;
102 : ptss(pts), boxes(nullptr), npts(pts.size()), ptindx(npts), rptindx(npts) {
103 MInt ntmp, m, k, kk, j, nowtask, jbox, np, tmom, tdim, ptlo, pthi;
106 MInt taskmom[50], taskdim[50];
107 if(
npts == 0)
return;
108 for(k = 0; k <
npts; k++)
111 for(ntmp =
npts; ntmp; ntmp >>= 1) {
120 for(j = 0, kk = 0; j < DIM; j++, kk +=
npts) {
121 for(k = 0; k <
npts; k++)
122 coords[kk + k] = pts[k].x[j];
131 tmom = taskmom[nowtask];
132 tdim = taskdim[nowtask--];
133 ptlo =
boxes[tmom].ptlo;
134 pthi =
boxes[tmom].pthi;
136 cp = &coords[tdim *
npts];
137 np = pthi - ptlo + 1;
139 (void)selecti<DIM>(kk, hp, np, cp);
142 hi.
x[tdim] = lo.x[tdim] = coords[tdim *
npts + hp[kk]];
148 taskmom[++nowtask] = jbox - 1;
149 taskdim[nowtask] = (tdim + 1) % DIM;
152 taskmom[++nowtask] = jbox;
153 taskdim[nowtask] = (tdim + 1) % DIM;
156 for(j = 0; j <
npts; j++)
166 return dist(ptss[jpt], ptss[kpt]);
172 while(boxes[nb].dau1) {
174 if(pt.
x[jdim] <= boxes[d1].hi.x[jdim])
189 while(boxes[nb].dau1) {
191 if(jh <= boxes[d1].pthi)
205 for(i = boxes[k].ptlo; i <= boxes[k].pthi; i++) {
206 d =
dist(ptss[ptindx[i]], pt);
216 if(
dist(boxes[k], pt) < dnrst) {
218 task[++ntask] = boxes[k].dau1;
219 task[++ntask] = boxes[k].dau2;
221 for(i = boxes[k].ptlo; i <= boxes[k].pthi; i++) {
222 d =
dist(ptss[ptindx[i]], pt);
231 dist1 =
dist(ptss[nrst], pt);
232 return ptss[nrst].cellId;
236 MInt i, k, ntask, kp;
239 ASSERT(!(n > npts - 1),
"too many neighbors requested");
240 for(i = 0; i < n; i++)
242 for(i = 0; i < n; i++)
248 nn[0] = ptss[ptindx[0]].cellId;
249 dn[0] = disti(ptindx[0], jpt);
251 }
else if(npts == 2) {
252 MInt smaller = (disti(ptindx[0], jpt) < disti(ptindx[1], jpt)) ? 0 : 1;
253 MInt other = (smaller + 1) % 2;
254 nn[0] = ptss[ptindx[smaller]].cellId;
255 dn[0] = disti(ptindx[smaller], jpt);
257 nn[1] = ptss[ptindx[other]].cellId;
258 dn[1] = disti(ptindx[other], jpt);
262 kp = boxes[locate(jpt)].mom;
263 while(boxes[kp].pthi - boxes[kp].ptlo < n)
265 for(i = boxes[kp].ptlo; i <= boxes[kp].pthi; i++) {
266 if(jpt == ptindx[i])
continue;
267 d = disti(ptindx[i], jpt);
271 if(n > 1) sift_down(dn, nn, n);
278 if(k == kp)
continue;
279 if(
dist(boxes[k], ptss[jpt]) < dn[0]) {
281 task[++ntask] = boxes[k].dau1;
282 task[++ntask] = boxes[k].dau2;
284 for(i = boxes[k].ptlo; i <= boxes[k].pthi; i++) {
285 d = disti(ptindx[i], jpt);
289 if(n > 1) sift_down(dn, nn, n);
295 for(i = 0; i < n; i++)
296 nn[i] = (nn[i] > -1) ? ptss[nn[i]].cellId : -1;
309 if(j < n && heap[j] < heap[j + 1]) j++;
310 if(
a >= heap[j])
break;
311 heap[jold] = heap[j];
321 MInt k, i, nb, nbold, nret, ntask, jdim, d1, d2;
323 nb = jdim = nret = 0;
324 ASSERT(!(r < 0.0),
"radius must be nonnegative");
325 ASSERT(nmax > 0,
"");
328 }
else if(npts == 1) {
329 if(
dist(ptss[ptindx[0]], pt) < r && nmax > 0) list[nret++] = ptss[ptindx[0]].cellId;
330 }
else if(npts == 2) {
331 if(
dist(ptss[ptindx[0]], pt) < r && nmax > 0) list[nret++] = ptss[ptindx[0]].cellId;
332 if(
dist(ptss[ptindx[1]], pt) < r && nmax > 1) list[nret++] = ptss[ptindx[1]].cellId;
334 while(boxes[nb].dau1) {
338 if(pt.
x[jdim] + r <= boxes[d1].hi.x[jdim])
340 else if(pt.
x[jdim] - r >= boxes[d2].lo.x[jdim])
343 jdim = (jdim + 1) % DIM;
344 if(nb == nbold)
break;
350 if(
dist(boxes[k], pt) > r)
continue;
352 task[++ntask] = boxes[k].dau1;
353 task[++ntask] = boxes[k].dau2;
355 for(i = boxes[k].ptlo; i <= boxes[k].pthi; i++) {
356 if(
dist(ptss[ptindx[i]], pt) <= r && nret < nmax) {
358 list[nret++] = ptss[ptindx[i]].cellId;
360 list[nret++] = ptindx[i];
364 if(nret == nmax)
return nmax;
373 MInt k, i, nb, nbold, nret, ntask, jdim, d1, d2;
375 nb = jdim = nret = 0;
377 ASSERT(!(r < 0.0),
"radius must be nonnegative");
378 ASSERT(nmax > 0,
"");
381 }
else if(npts == 1) {
382 if(
dist(ptss[ptindx[0]], pt) < r && nmax > 0) list[nret++] = ptss[ptindx[0]].cellId;
383 }
else if(npts == 2) {
384 MInt smaller = (
dist(ptss[ptindx[0]], pt) <
dist(ptss[ptindx[1]], pt)) ? 0 : 1;
385 MInt other = (smaller + 1) % 2;
386 if(
dist(ptss[ptindx[smaller]], pt) < r && nmax > 0) list[nret++] = ptss[ptindx[smaller]].cellId;
387 if(
dist(ptss[ptindx[other]], pt) < r && nmax > 1) list[nret++] = ptss[ptindx[other]].cellId;
389 while(boxes[nb].dau1) {
393 if(pt.
x[jdim] + r <= boxes[d1].hi.x[jdim])
395 else if(pt.
x[jdim] - r >= boxes[d2].lo.x[jdim])
398 jdim = (jdim + 1) % DIM;
399 if(nb == nbold)
break;
405 if(
dist(boxes[k], pt) > r)
continue;
407 task[++ntask] = boxes[k].dau1;
408 task[++ntask] = boxes[k].dau2;
410 for(i = boxes[k].ptlo; i <= boxes[k].pthi; i++) {
413 if(nret == nmax) overflow =
true;
415 for(s = 0; s < nret; s++) {
417 for(
MInt t = std::min(nret, nmax - 1); t > s; t--) {
418 list[t] = list[t - 1];
425 list[s] = ptss[ptindx[i]].cellId;
428 if(nret < nmax) nret++;
MInt selecti(const MInt k, MInt *indx, MInt n, MFloat *arr)
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Boxnode(Point< DIM > mylo, Point< DIM > myhi, MInt mymom, MInt myd1, MInt myd2, MInt myptlo, MInt mypthi)
static void sift_down(MFloat *heap, MInt *ndx, MInt nn)
MInt nearest(Point< DIM > pt, MFloat &dist)
MInt locatenear(Point< DIM > pt, MFloat r, MInt *list, MInt nmax, MBool returnCellId=true)
std::vector< Point< DIM > > ptss
KDtree(std::vector< Point< DIM > > &pts)
MInt locate(Point< DIM > pt)
MFloat disti(MInt jpt, MInt kpt)
MInt locatenearest(Point< DIM > pt, MFloat r, MInt *list, MFloat *dn, MInt nmax, MBool &overflow)
std::vector< MInt > ptindx
void nnearest(MInt jpt, MInt *nn, MFloat *dn, MInt n)
std::vector< MInt > rptindx