Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
QuadTree.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <sparse/general.h>
12#include <common/geom.h>
13#include <common/arith.h>
14#include <math.h>
15#include <sparse/QuadTree.h>
16#include <stdbool.h>
17#include <stddef.h>
18#include <util/alloc.h>
19
20extern double distance_cropped(double *x, int dim, int i, int j);
21
22static node_data node_data_new(int dim, double weight, double *coord, int id){
23 int i;
24 node_data nd = gv_alloc(sizeof(struct node_data_struct));
25 nd->node_weight = weight;
26 nd->coord = gv_calloc(dim, sizeof(double));
27 nd->id = id;
28 for (i = 0; i < dim; i++) nd->coord[i] = coord[i];
29 nd->data = NULL;
30 return nd;
31}
32
34 free(nd->coord);
35 /*delete outside if (nd->data) free(nd->data);*/
36 free(nd);
37}
38
39static void check_or_realloc_arrays(int dim, int *nsuper, int *nsupermax, double **center, double **supernode_wgts, double **distances){
40
41 if (*nsuper >= *nsupermax) {
42 int new_nsupermax = *nsuper + 10;
43 *center = gv_recalloc(*center, dim * *nsupermax, dim * new_nsupermax, sizeof(double));
44 *supernode_wgts = gv_recalloc(*supernode_wgts, *nsupermax, new_nsupermax, sizeof(double));
45 *distances = gv_recalloc(*distances, *nsupermax, new_nsupermax, sizeof(double));
46 *nsupermax = new_nsupermax;
47 }
48}
49
50static void QuadTree_get_supernodes_internal(QuadTree qt, double bh, double *pt, int nodeid, int *nsuper, int *nsupermax, double **center, double **supernode_wgts, double **distances, double *counts) {
51 double *coord, dist;
52 int dim, i;
53
54 (*counts)++;
55
56 if (!qt) return;
57 dim = qt->dim;
58 node_data l = qt->l;
59 while (l) {
60 check_or_realloc_arrays(dim, nsuper, nsupermax, center, supernode_wgts, distances);
61 if (l->id != nodeid){
62 coord = l->coord;
63 for (i = 0; i < dim; i++){
64 (*center)[dim*(*nsuper)+i] = coord[i];
65 }
66 (*supernode_wgts)[*nsuper] = l->node_weight;
67 (*distances)[*nsuper] = point_distance(pt, coord, dim);
68 (*nsuper)++;
69 }
70 l = l->next;
71 }
72
73 if (qt->qts){
74 dist = point_distance(qt->center, pt, dim);
75 if (qt->width < bh*dist){
76 check_or_realloc_arrays(dim, nsuper, nsupermax, center, supernode_wgts, distances);
77 for (i = 0; i < dim; i++){
78 (*center)[dim*(*nsuper)+i] = qt->average[i];
79 }
80 (*supernode_wgts)[*nsuper] = qt->total_weight;
81 (*distances)[*nsuper] = point_distance(qt->average, pt, dim);
82 (*nsuper)++;
83 } else {
84 for (i = 0; i < 1<<dim; i++){
85 QuadTree_get_supernodes_internal(qt->qts[i], bh, pt, nodeid, nsuper, nsupermax, center,
86 supernode_wgts, distances, counts);
87 }
88 }
89 }
90
91}
92
93void QuadTree_get_supernodes(QuadTree qt, double bh, double *pt, int nodeid, int *nsuper,
94 int *nsupermax, double **center, double **supernode_wgts, double **distances, double *counts) {
95 int dim = qt->dim;
96
97 (*counts) = 0;
98
99 *nsuper = 0;
100
101 *nsupermax = 10;
102 if (!*center) *center = gv_calloc(*nsupermax * dim, sizeof(double));
103 if (!*supernode_wgts) *supernode_wgts = gv_calloc(*nsupermax, sizeof(double));
104 if (!*distances) *distances = gv_calloc(*nsupermax, sizeof(double));
105 QuadTree_get_supernodes_internal(qt, bh, pt, nodeid, nsuper, nsupermax, center, supernode_wgts, distances, counts);
106
107}
108
109static double *get_or_assign_node_force(double *force, int i, node_data l,
110 int dim) {
111
112 double *f = l->data;
113
114 if (!f){
115 l->data = &(force[i*dim]);
116 f = l->data;
117 }
118 return f;
119}
120static double *get_or_alloc_force_qt(QuadTree qt, int dim){
121 double *force = qt->data;
122 if (!force){
123 qt->data = gv_calloc(dim, sizeof(double));
124 force = qt->data;
125 }
126 return force;
127}
128
129static void QuadTree_repulsive_force_interact(QuadTree qt1, QuadTree qt2, double *x, double *force, double bh, double p, double KP, double *counts){
130 // calculate the all to all repulsive force and accumulate on each node of the
131 // quadtree if an interaction is possible.
132 // force[i × dim + j], j=1,..., dim is the force on node i
133 double *x1, *x2, dist, wgt1, wgt2, f, *f1, *f2, w1, w2;
134 int dim, i, j, i1, i2, k;
135 QuadTree qt11, qt12;
136
137 if (!qt1 || !qt2) return;
138 assert(qt1->n > 0 && qt2->n > 0);
139 dim = qt1->dim;
140
141 node_data l1 = qt1->l;
142 node_data l2 = qt2->l;
143
144 /* far enough, calculate repulsive force */
145 dist = point_distance(qt1->average, qt2->average, dim);
146 if (qt1->width + qt2->width < bh*dist){
147 counts[0]++;
148 x1 = qt1->average;
149 w1 = qt1->total_weight;
150 f1 = get_or_alloc_force_qt(qt1, dim);
151 x2 = qt2->average;
152 w2 = qt2->total_weight;
153 f2 = get_or_alloc_force_qt(qt2, dim);
154 assert(dist > 0);
155 for (k = 0; k < dim; k++){
156 if (p == -1){
157 f = w1*w2*KP*(x1[k] - x2[k])/(dist*dist);
158 } else {
159 f = w1*w2*KP*(x1[k] - x2[k])/pow(dist, 1.- p);
160 }
161 f1[k] += f;
162 f2[k] -= f;
163 }
164 return;
165 }
166
167
168 /* both at leaves, calculate repulsive force */
169 if (l1 && l2){
170 while (l1){
171 x1 = l1->coord;
172 wgt1 = l1->node_weight;
173 i1 = l1->id;
174 f1 = get_or_assign_node_force(force, i1, l1, dim);
175 l2 = qt2->l;
176 while (l2){
177 x2 = l2->coord;
178 wgt2 = l2->node_weight;
179 i2 = l2->id;
180 f2 = get_or_assign_node_force(force, i2, l2, dim);
181 if ((qt1 == qt2 && i2 < i1) || i1 == i2) {
182 l2 = l2->next;
183 continue;
184 }
185 counts[1]++;
186 dist = distance_cropped(x, dim, i1, i2);
187 for (k = 0; k < dim; k++){
188 if (p == -1){
189 f = wgt1*wgt2*KP*(x1[k] - x2[k])/(dist*dist);
190 } else {
191 f = wgt1*wgt2*KP*(x1[k] - x2[k])/pow(dist, 1.- p);
192 }
193 f1[k] += f;
194 f2[k] -= f;
195 }
196 l2 = l2->next;
197 }
198 l1 = l1->next;
199 }
200 return;
201 }
202
203
204 /* identical, split one */
205 if (qt1 == qt2){
206 for (i = 0; i < 1<<dim; i++){
207 qt11 = qt1->qts[i];
208 for (j = i; j < 1<<dim; j++){
209 qt12 = qt1->qts[j];
210 QuadTree_repulsive_force_interact(qt11, qt12, x, force, bh, p, KP, counts);
211 }
212 }
213 } else {
214 /* split the one with bigger box, or one not at the last level */
215 if (qt1->width > qt2->width && !l1){
216 for (i = 0; i < 1<<dim; i++){
217 qt11 = qt1->qts[i];
218 QuadTree_repulsive_force_interact(qt11, qt2, x, force, bh, p, KP, counts);
219 }
220 } else if (qt2->width > qt1->width && !l2){
221 for (i = 0; i < 1<<dim; i++){
222 qt11 = qt2->qts[i];
223 QuadTree_repulsive_force_interact(qt11, qt1, x, force, bh, p, KP, counts);
224 }
225 } else if (!l1){/* pick one that is not at the last level */
226 for (i = 0; i < 1<<dim; i++){
227 qt11 = qt1->qts[i];
228 QuadTree_repulsive_force_interact(qt11, qt2, x, force, bh, p, KP, counts);
229 }
230 } else if (!l2){
231 for (i = 0; i < 1<<dim; i++){
232 qt11 = qt2->qts[i];
233 QuadTree_repulsive_force_interact(qt11, qt1, x, force, bh, p, KP, counts);
234 }
235 } else {
236 assert(0); // can be both at the leaf level since that should be caught at
237 // the beginning of this func
238 }
239 }
240}
241
242static void QuadTree_repulsive_force_accumulate(QuadTree qt, double *force, double *counts){
243 /* push down forces on cells into the node level */
244 double wgt, wgt2;
245 double *f, *f2;
246 node_data l = qt->l;
247 int i, k, dim;
248 QuadTree qt2;
249
250 dim = qt->dim;
251 wgt = qt->total_weight;
252 f = get_or_alloc_force_qt(qt, dim);
253 assert(wgt > 0);
254 counts[2]++;
255
256 if (l){
257 while (l){
258 i = l->id;
259 f2 = get_or_assign_node_force(force, i, l, dim);
260 wgt2 = l->node_weight;
261 wgt2 = wgt2/wgt;
262 for (k = 0; k < dim; k++) f2[k] += wgt2*f[k];
263 l = l->next;
264 }
265 return;
266 }
267
268 for (i = 0; i < 1<<dim; i++){
269 qt2 = qt->qts[i];
270 if (!qt2) continue;
271 assert(qt2->n > 0);
272 f2 = get_or_alloc_force_qt(qt2, dim);
273 wgt2 = qt2->total_weight;
274 wgt2 = wgt2/wgt;
275 for (k = 0; k < dim; k++) f2[k] += wgt2*f[k];
276 QuadTree_repulsive_force_accumulate(qt2, force, counts);
277 }
278
279}
280
281void QuadTree_get_repulsive_force(QuadTree qt, double *force, double *x, double bh, double p, double KP, double *counts){
282 // get repulsive force by a more efficient algorithm: we consider two cells,
283 // if they are well separated, we calculate the overall repulsive force on the
284 // cell level, if not well separated, we divide one of the cell. If both cells
285 // are at the leaf level, we calculate repulsive force among individual nodes.
286 // Finally we accumulate forces at the cell levels to the node level
287 // qt: the quadtree
288 // x: current coordinates for node i is x[i*dim+j], j = 0, ..., dim-1
289 // force: the repulsive force, an array of length dim*nnodes, the force for node i is at force[i*dim+j], j = 0, ..., dim - 1
290 // bh: Barnes-Hut coefficient. If width_cell1+width_cell2 < bh*dist_between_cells, we treat each cell as a supernode.
291 // p: the repulsive force power
292 // KP: pow(K, 1 - p)
293 // counts: array of size 4.
294 // . counts[0]: number of cell-cell interaction
295 // . counts[1]: number of cell-node interaction
296 // . counts[2]: number of total cells in the quadtree
297 // . Al normalized by dividing by number of nodes
298 int n = qt->n, dim = qt->dim, i;
299
300 for (i = 0; i < 4; i++) counts[i] = 0;
301
302 for (i = 0; i < dim*n; i++) force[i] = 0;
303
304 QuadTree_repulsive_force_interact(qt, qt, x, force, bh, p, KP, counts);
305 QuadTree_repulsive_force_accumulate(qt, force, counts);
306 for (i = 0; i < 4; i++) counts[i] /= n;
307
308}
309QuadTree QuadTree_new_from_point_list(int dim, int n, int max_level, double *coord){
310 /* form a new QuadTree data structure from a list of coordinates of n points
311 coord: of length n*dim, point i sits at [i*dim, i*dim+dim - 1]
312 */
313 double *xmin, *xmax, *center, width;
314 QuadTree qt = NULL;
315 int i, k;
316
317 xmin = gv_calloc(dim, sizeof(double));
318 xmax = gv_calloc(dim, sizeof(double));
319 center = gv_calloc(dim, sizeof(double));
320 if (!xmin || !xmax || !center) {
321 free(xmin);
322 free(xmax);
323 free(center);
324 return NULL;
325 }
326
327 for (i = 0; i < dim; i++) xmin[i] = coord[i];
328 for (i = 0; i < dim; i++) xmax[i] = coord[i];
329
330 for (i = 1; i < n; i++){
331 for (k = 0; k < dim; k++){
332 xmin[k] = fmin(xmin[k], coord[i*dim+k]);
333 xmax[k] = fmax(xmax[k], coord[i*dim+k]);
334 }
335 }
336
337 width = xmax[0] - xmin[0];
338 for (i = 0; i < dim; i++) {
339 center[i] = (xmin[i] + xmax[i])*0.5;
340 width = fmax(width, xmax[i] - xmin[i]);
341 }
342 width = fmax(width, 0.00001);/* if we only have one point, width = 0! */
343 width *= 0.52;
344 qt = QuadTree_new(dim, center, width, max_level);
345
346 for (i = 0; i < n; i++){
347 qt = QuadTree_add(qt, &(coord[i*dim]), 1, i);
348 }
349
350
351 free(xmin);
352 free(xmax);
353 free(center);
354 return qt;
355}
356
357QuadTree QuadTree_new(int dim, double *center, double width, int max_level){
358 int i;
359 QuadTree q = gv_alloc(sizeof(struct QuadTree_struct));
360 q->dim = dim;
361 q->n = 0;
362 q->center = gv_calloc(dim, sizeof(double));
363 for (i = 0; i < dim; i++) q->center[i] = center[i];
364 assert(width > 0);
365 q->width = width;
366 q->total_weight = 0;
367 q->average = NULL;
368 q->qts = NULL;
369 q->l = NULL;
370 q->max_level = max_level;
371 q->data = NULL;
372 return q;
373}
374
376 int i, dim;
377 if (!q) return;
378 dim = q->dim;
379 free(q->center);
380 free(q->average);
381 free(q->data);
382 if (q->qts){
383 for (i = 0; i < 1<<dim; i++){
384 QuadTree_delete(q->qts[i]);
385 }
386 free(q->qts);
387 }
388 while (q->l) {
389 node_data next = q->l->next;
391 q->l = next;
392 }
393 free(q);
394}
395
396static int QuadTree_get_quadrant(int dim, double *center, double *coord){
397 /* find the quadrant that a point of coordinates coord is going into with reference to the center.
398 if coord - center == {+,-,+,+} = {1,0,1,1}, then it will sit in the i-quadrant where
399 i's binary representation is 1011 (that is, decimal 11).
400 */
401 int d = 0, i;
402
403 for (i = dim - 1; i >= 0; i--){
404 if (coord[i] - center[i] < 0){
405 d = 2*d;
406 } else {
407 d = 2*d+1;
408 }
409 }
410 return d;
411}
412
413QuadTree QuadTree_new_in_quadrant(int dim, double *center, double width, int max_level, int i){
414 /* a new quadtree in quadrant i of the original cell. The original cell is centered at 'center".
415 The new cell have width "width".
416 */
417 QuadTree qt;
418 int k;
419
420 qt = QuadTree_new(dim, center, width, max_level);
421 center = qt->center;/* right now this has the center for the parent */
422 for (k = 0; k < dim; k++){/* decompose child id into binary, if {1,0}, say, then
423 add {width/2, -width/2} to the parents' center
424 to get the child's center. */
425 if (i%2 == 0){
426 center[k] -= width;
427 } else {
428 center[k] += width;
429 }
430 i = (i - i%2)/2;
431 }
432 return qt;
433
434}
435static QuadTree QuadTree_add_internal(QuadTree q, double *coord, double weight, int id, int level){
436 int i, dim = q->dim, ii;
437 node_data nd = NULL;
438
439 int max_level = q->max_level;
440 int idd;
441
442 /* Make sure that coord is within bounding box */
443 for (i = 0; i < q->dim; i++) {
444 if (coord[i] < q->center[i] - q->width - 1.e5*MACHINEACC*q->width || coord[i] > q->center[i] + q->width + 1.e5*MACHINEACC*q->width) {
445#ifdef DEBUG_PRINT
446 fprintf(stderr,"coordinate %f is outside of the box:{%f, %f}, \n(q->center[i] - q->width) - coord[i] =%g, coord[i]-(q->center[i] + q->width) = %g\n",coord[i], (q->center[i] - q->width), (q->center[i] + q->width),
447 (q->center[i] - q->width) - coord[i], coord[i]-(q->center[i] + q->width));
448#endif
449 //return NULL;
450 }
451 }
452
453 if (q->n == 0){
454 /* if this node is empty right now */
455 q->n = 1;
456 q->total_weight = weight;
457 q->average = gv_calloc(dim, sizeof(double));
458 for (i = 0; i < q->dim; i++) q->average[i] = coord[i];
459 nd = node_data_new(q->dim, weight, coord, id);
460 assert(!(q->l));
461 q->l = nd;
462 } else if (level < max_level){
463 /* otherwise open up into 2^dim quadtrees unless the level is too high */
464 q->total_weight += weight;
465 for (i = 0; i < q->dim; i++) q->average[i] = (q->average[i] * q->n + coord[i]) / (q->n + 1);
466 if (!q->qts){
467 q->qts = gv_calloc((size_t)1 << dim, sizeof(QuadTree));
468 }/* done adding new quadtree, now add points to them */
469
470 /* insert the old node (if exist) and the current node into the appropriate child quadtree */
472 assert(ii < 1<<dim && ii >= 0);
473 if (q->qts[ii] == NULL) q->qts[ii] = QuadTree_new_in_quadrant(q->dim, q->center, q->width / 2, max_level, ii);
474
475 q->qts[ii] = QuadTree_add_internal(q->qts[ii], coord, weight, id, level + 1);
476 assert(q->qts[ii]);
477
478 if (q->l){
479 idd = q->l->id;
480 assert(q->n == 1);
481 coord = q->l->coord;
482 weight = q->l->node_weight;
484 assert(ii < 1<<dim && ii >= 0);
485
486 if (q->qts[ii] == NULL) q->qts[ii] = QuadTree_new_in_quadrant(q->dim, q->center, (q->width)/2, max_level, ii);
487
488 q->qts[ii] = QuadTree_add_internal(q->qts[ii], coord, weight, idd, level + 1);
489 assert(q->qts[ii]);
490
491 /* delete the old node data on parent */
492 while (q->l != NULL) {
493 node_data next = q->l->next;
495 q->l = next;
496 }
497 }
498
499 q->n++;
500 } else {
501 assert(!(q->qts));
502 /* level is too high, append data in the linked list */
503 q->n++;
504 q->total_weight += weight;
505 for (i = 0; i < q->dim; i++) q->average[i] = (q->average[i] * q->n + coord[i]) / (q->n + 1);
506 nd = node_data_new(q->dim, weight, coord, id);
507 assert(q->l);
508 nd->next = q->l;
509 q->l = nd;
510 }
511 return q;
512}
513
514
515QuadTree QuadTree_add(QuadTree q, double *coord, double weight, int id){
516 if (!q) return q;
517 return QuadTree_add_internal(q, coord, weight, id, 0);
518
519}
520
521static void draw_polygon(FILE *fp, int dim, double *center, double width){
522 // plot the enclosing square
523 if (dim < 2 || dim > 3) return;
524 fprintf(fp,"(*in c*){Line[{");
525
526 if (dim == 2){
527 fprintf(fp, "{%f, %f}", center[0] + width, center[1] + width);
528 fprintf(fp, ",{%f, %f}", center[0] - width, center[1] + width);
529 fprintf(fp, ",{%f, %f}", center[0] - width, center[1] - width);
530 fprintf(fp, ",{%f, %f}", center[0] + width, center[1] - width);
531 fprintf(fp, ",{%f, %f}", center[0] + width, center[1] + width);
532 } else if (dim == 3){
533 /* top */
534 fprintf(fp,"{");
535 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] + width);
536 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] + width, center[2] + width);
537 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] - width, center[2] + width);
538 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] - width, center[2] + width);
539 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] + width, center[2] + width);
540 fprintf(fp,"},");
541 /* bot */
542 fprintf(fp,"{");
543 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] - width);
544 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] + width, center[2] - width);
545 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] - width, center[2] - width);
546 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] - width, center[2] - width);
547 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] + width, center[2] - width);
548 fprintf(fp,"},");
549 /* for sides */
550 fprintf(fp,"{");
551 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] - width);
552 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] + width, center[2] + width);
553 fprintf(fp,"},");
554
555 fprintf(fp,"{");
556 fprintf(fp, "{%f, %f, %f}", center[0] - width, center[1] + width, center[2] - width);
557 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] + width, center[2] + width);
558 fprintf(fp,"},");
559
560 fprintf(fp,"{");
561 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] - width, center[2] - width);
562 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] - width, center[2] + width);
563 fprintf(fp,"},");
564
565 fprintf(fp,"{");
566 fprintf(fp, "{%f, %f, %f}", center[0] - width, center[1] - width, center[2] - width);
567 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] - width, center[2] + width);
568 fprintf(fp,"}");
569 }
570
571
572 fprintf(fp, "}]}(*end C*)");
573
574
575}
576static void QuadTree_print_internal(FILE *fp, QuadTree q, int level){
577 /* dump a quad tree in Mathematica format. */
578 node_data l, l0;
579 double *coord;
580 int i, dim;
581
582 if (!q) return;
583
584 draw_polygon(fp, q->dim, q->center, q->width);
585 dim = q->dim;
586
587 l0 = l = q->l;
588 if (l){
589 printf(",(*a*) {Red,");
590 while (l){
591 if (l != l0) printf(",");
592 coord = l->coord;
593 fprintf(fp, "(*node %d*) Point[{", l->id);
594 for (i = 0; i < dim; i++){
595 if (i != 0) printf(",");
596 fprintf(fp, "%f",coord[i]);
597 }
598 fprintf(fp, "}]");
599 l = l->next;
600 }
601 fprintf(fp, "}");
602 }
603
604 if (q->qts){
605 for (i = 0; i < 1<<dim; i++){
606 fprintf(fp, ",(*b*){");
607 QuadTree_print_internal(fp, q->qts[i], level + 1);
608 fprintf(fp, "}");
609 }
610 }
611
612
613}
614
615void QuadTree_print(FILE *fp, QuadTree q){
616 if (!fp) return;
617 if (q->dim == 2){
618 fprintf(fp, "Graphics[{");
619 } else if (q->dim == 3){
620 fprintf(fp, "Graphics3D[{");
621 } else {
622 return;
623 }
624 QuadTree_print_internal(fp, q, 0);
625 if (q->dim == 2){
626 fprintf(fp, "}, PlotRange -> All, Frame -> True, FrameTicks -> True]\n");
627 } else {
628 fprintf(fp, "}, PlotRange -> All]\n");
629 }
630}
631
632static void QuadTree_get_nearest_internal(QuadTree qt, double *x, double *y,
633 double *min, int *imin,
634 bool tentative) {
635 /* get the nearest point years to {x[0], ..., x[dim]} and store in y.*/
636 double *coord, dist;
637 int dim, i, iq = -1;
638 double qmin;
639
640 if (!qt) return;
641 dim = qt->dim;
642 node_data l = qt->l;
643 while (l){
644 coord = l->coord;
646 if(*min < 0 || dist < *min) {
647 *min = dist;
648 *imin = l->id;
649 for (i = 0; i < dim; i++) y[i] = coord[i];
650 }
651 l = l->next;
652 }
653
654 if (qt->qts){
655 dist = point_distance(qt->center, x, dim);
656 if (*min >= 0 && (dist - sqrt((double) dim) * qt->width > *min)){
657 return;
658 } else {
659 if (tentative){/* quick first approximation*/
660 qmin = -1;
661 for (i = 0; i < 1<<dim; i++){
662 if (qt->qts[i]){
663 dist = point_distance(qt->qts[i]->average, x, dim);
664 if (dist < qmin || qmin < 0){
665 qmin = dist; iq = i;
666 }
667 }
668 }
669 assert(iq >= 0);
670 QuadTree_get_nearest_internal(qt->qts[iq], x, y, min, imin, tentative);
671 } else {
672 for (i = 0; i < 1<<dim; i++){
673 QuadTree_get_nearest_internal(qt->qts[i], x, y, min, imin, tentative);
674 }
675 }
676 }
677 }
678
679}
680
681
682void QuadTree_get_nearest(QuadTree qt, double *x, double *ymin, int *imin, double *min){
683
684 *min = -1;
685
686 QuadTree_get_nearest_internal(qt, x, ymin, min, imin, true);
687 QuadTree_get_nearest_internal(qt, x, ymin, min, imin, false);
688}
void QuadTree_get_nearest(QuadTree qt, double *x, double *ymin, int *imin, double *min)
Definition QuadTree.c:682
static void QuadTree_print_internal(FILE *fp, QuadTree q, int level)
Definition QuadTree.c:576
void QuadTree_get_repulsive_force(QuadTree qt, double *force, double *x, double bh, double p, double KP, double *counts)
Definition QuadTree.c:281
QuadTree QuadTree_add(QuadTree q, double *coord, double weight, int id)
Definition QuadTree.c:515
static void draw_polygon(FILE *fp, int dim, double *center, double width)
Definition QuadTree.c:521
QuadTree QuadTree_new_in_quadrant(int dim, double *center, double width, int max_level, int i)
Definition QuadTree.c:413
static void node_data_delete(node_data nd)
Definition QuadTree.c:33
QuadTree QuadTree_new_from_point_list(int dim, int n, int max_level, double *coord)
Definition QuadTree.c:309
static void check_or_realloc_arrays(int dim, int *nsuper, int *nsupermax, double **center, double **supernode_wgts, double **distances)
Definition QuadTree.c:39
void QuadTree_print(FILE *fp, QuadTree q)
Definition QuadTree.c:615
static double * get_or_assign_node_force(double *force, int i, node_data l, int dim)
Definition QuadTree.c:109
QuadTree QuadTree_new(int dim, double *center, double width, int max_level)
Definition QuadTree.c:357
static double * get_or_alloc_force_qt(QuadTree qt, int dim)
Definition QuadTree.c:120
static node_data node_data_new(int dim, double weight, double *coord, int id)
Definition QuadTree.c:22
static void QuadTree_repulsive_force_interact(QuadTree qt1, QuadTree qt2, double *x, double *force, double bh, double p, double KP, double *counts)
Definition QuadTree.c:129
static QuadTree QuadTree_add_internal(QuadTree q, double *coord, double weight, int id, int level)
Definition QuadTree.c:435
static void QuadTree_repulsive_force_accumulate(QuadTree qt, double *force, double *counts)
Definition QuadTree.c:242
static int QuadTree_get_quadrant(int dim, double *center, double *coord)
Definition QuadTree.c:396
static void QuadTree_get_supernodes_internal(QuadTree qt, double bh, double *pt, int nodeid, int *nsuper, int *nsupermax, double **center, double **supernode_wgts, double **distances, double *counts)
Definition QuadTree.c:50
void QuadTree_delete(QuadTree q)
Definition QuadTree.c:375
double distance_cropped(double *x, int dim, int i, int j)
Definition general.c:140
static void QuadTree_get_nearest_internal(QuadTree qt, double *x, double *y, double *min, int *imin, bool tentative)
Definition QuadTree.c:632
void QuadTree_get_supernodes(QuadTree qt, double bh, double *pt, int nodeid, int *nsuper, int *nsupermax, double **center, double **supernode_wgts, double **distances, double *counts)
Definition QuadTree.c:93
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
static double dist(int dim, double *x, double *y)
double point_distance(double *p1, double *p2, int dim)
Definition general.c:153
#define MACHINEACC
Definition general.h:76
geometric types and macros (e.g. points and boxes)
double xmax
Definition geometry.c:15
double ymin
Definition geometry.c:15
double xmin
Definition geometry.c:15
void free(void *)
node NULL
Definition grammar.y:163
static uint64_t id
Definition gv2gml.c:42
static int imin(int a, int b)
minimum of two integers
Definition gv_math.h:27
static const int dim
pointf coord(node_t *n)
Definition utils.c:150
static const double bh
node_data l
Definition QuadTree.h:44
double total_weight
Definition QuadTree.h:37
double * average
Definition QuadTree.h:42
QuadTree * qts
Definition QuadTree.h:43
double * center
Definition QuadTree.h:39
double * coord
Definition QuadTree.h:23
node_data next
Definition QuadTree.h:26
double node_weight
Definition QuadTree.h:22
static point center(point vertex[], size_t n)