Graphviz 12.0.1~dev.20240716.0800
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 <cgraph/alloc.h>
12#include <sparse/general.h>
13#include <common/geom.h>
14#include <common/arith.h>
15#include <math.h>
16#include <sparse/QuadTree.h>
17#include <stdbool.h>
18#include <stddef.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 reopulsive force and accumulate on each node of the quadtree if an interaction is possible.
131 force[i*dim+j], j=1,...,dim is the force on node i
132 */
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 catched at the beginning of this func. */
237 }
238 }
239}
240
241static void QuadTree_repulsive_force_accumulate(QuadTree qt, double *force, double *counts){
242 /* push down forces on cells into the node level */
243 double wgt, wgt2;
244 double *f, *f2;
245 node_data l = qt->l;
246 int i, k, dim;
247 QuadTree qt2;
248
249 dim = qt->dim;
250 wgt = qt->total_weight;
251 f = get_or_alloc_force_qt(qt, dim);
252 assert(wgt > 0);
253 counts[2]++;
254
255 if (l){
256 while (l){
257 i = l->id;
258 f2 = get_or_assign_node_force(force, i, l, dim);
259 wgt2 = l->node_weight;
260 wgt2 = wgt2/wgt;
261 for (k = 0; k < dim; k++) f2[k] += wgt2*f[k];
262 l = l->next;
263 }
264 return;
265 }
266
267 for (i = 0; i < 1<<dim; i++){
268 qt2 = qt->qts[i];
269 if (!qt2) continue;
270 assert(qt2->n > 0);
271 f2 = get_or_alloc_force_qt(qt2, dim);
272 wgt2 = qt2->total_weight;
273 wgt2 = wgt2/wgt;
274 for (k = 0; k < dim; k++) f2[k] += wgt2*f[k];
275 QuadTree_repulsive_force_accumulate(qt2, force, counts);
276 }
277
278}
279
280void QuadTree_get_repulsive_force(QuadTree qt, double *force, double *x, double bh, double p, double KP, double *counts){
281 /* get repulsice force by a more efficient algortihm: we consider two cells, if they are well separated, we
282 calculate the overall repulsive force on the cell level, if not well separated, we divide one of the cell.
283 If both cells are at the leaf level, we calcuaulate repulsicve force among individual nodes. Finally
284 we accumulate forces at the cell levels to the node level
285 qt: the quadtree
286 x: current coordinates for node i is x[i*dim+j], j = 0, ..., dim-1
287 force: the repulsice force, an array of length dim*nnodes, the force for node i is at force[i*dim+j], j = 0, ..., dim - 1
288 bh: Barnes-Hut coefficient. If width_cell1+width_cell2 < bh*dist_between_cells, we treat each cell as a supernode.
289 p: the repulsive force power
290 KP: pow(K, 1 - p)
291 counts: array of size 4.
292 . counts[0]: number of cell-cell interaction
293 . counts[1]: number of cell-node interaction
294 . counts[2]: number of total cells in the quadtree
295 . Al normalized by dividing by number of nodes
296 */
297 int n = qt->n, dim = qt->dim, i;
298
299 for (i = 0; i < 4; i++) counts[i] = 0;
300
301 for (i = 0; i < dim*n; i++) force[i] = 0;
302
303 QuadTree_repulsive_force_interact(qt, qt, x, force, bh, p, KP, counts);
304 QuadTree_repulsive_force_accumulate(qt, force, counts);
305 for (i = 0; i < 4; i++) counts[i] /= n;
306
307}
308QuadTree QuadTree_new_from_point_list(int dim, int n, int max_level, double *coord){
309 /* form a new QuadTree data structure from a list of coordinates of n points
310 coord: of length n*dim, point i sits at [i*dim, i*dim+dim - 1]
311 */
312 double *xmin, *xmax, *center, width;
313 QuadTree qt = NULL;
314 int i, k;
315
316 xmin = gv_calloc(dim, sizeof(double));
317 xmax = gv_calloc(dim, sizeof(double));
318 center = gv_calloc(dim, sizeof(double));
319 if (!xmin || !xmax || !center) {
320 free(xmin);
321 free(xmax);
322 free(center);
323 return NULL;
324 }
325
326 for (i = 0; i < dim; i++) xmin[i] = coord[i];
327 for (i = 0; i < dim; i++) xmax[i] = coord[i];
328
329 for (i = 1; i < n; i++){
330 for (k = 0; k < dim; k++){
331 xmin[k] = fmin(xmin[k], coord[i*dim+k]);
332 xmax[k] = fmax(xmax[k], coord[i*dim+k]);
333 }
334 }
335
336 width = xmax[0] - xmin[0];
337 for (i = 0; i < dim; i++) {
338 center[i] = (xmin[i] + xmax[i])*0.5;
339 width = fmax(width, xmax[i] - xmin[i]);
340 }
341 width = fmax(width, 0.00001);/* if we only have one point, width = 0! */
342 width *= 0.52;
343 qt = QuadTree_new(dim, center, width, max_level);
344
345 for (i = 0; i < n; i++){
346 qt = QuadTree_add(qt, &(coord[i*dim]), 1, i);
347 }
348
349
350 free(xmin);
351 free(xmax);
352 free(center);
353 return qt;
354}
355
356QuadTree QuadTree_new(int dim, double *center, double width, int max_level){
357 int i;
358 QuadTree q = gv_alloc(sizeof(struct QuadTree_struct));
359 q->dim = dim;
360 q->n = 0;
361 q->center = gv_calloc(dim, sizeof(double));
362 for (i = 0; i < dim; i++) q->center[i] = center[i];
363 assert(width > 0);
364 q->width = width;
365 q->total_weight = 0;
366 q->average = NULL;
367 q->qts = NULL;
368 q->l = NULL;
369 q->max_level = max_level;
370 q->data = NULL;
371 return q;
372}
373
375 int i, dim;
376 if (!q) return;
377 dim = q->dim;
378 free(q->center);
379 free(q->average);
380 free(q->data);
381 if (q->qts){
382 for (i = 0; i < 1<<dim; i++){
383 QuadTree_delete(q->qts[i]);
384 }
385 free(q->qts);
386 }
387 while (q->l) {
388 node_data next = q->l->next;
390 q->l = next;
391 }
392 free(q);
393}
394
395static int QuadTree_get_quadrant(int dim, double *center, double *coord){
396 /* find the quadrant that a point of coordinates coord is going into with reference to the center.
397 if coord - center == {+,-,+,+} = {1,0,1,1}, then it will sit in the i-quadrant where
398 i's binary representation is 1011 (that is, decimal 11).
399 */
400 int d = 0, i;
401
402 for (i = dim - 1; i >= 0; i--){
403 if (coord[i] - center[i] < 0){
404 d = 2*d;
405 } else {
406 d = 2*d+1;
407 }
408 }
409 return d;
410}
411
412QuadTree QuadTree_new_in_quadrant(int dim, double *center, double width, int max_level, int i){
413 /* a new quadtree in quadrant i of the original cell. The original cell is centered at 'center".
414 The new cell have width "width".
415 */
416 QuadTree qt;
417 int k;
418
419 qt = QuadTree_new(dim, center, width, max_level);
420 center = qt->center;/* right now this has the center for the parent */
421 for (k = 0; k < dim; k++){/* decompose child id into binary, if {1,0}, say, then
422 add {width/2, -width/2} to the parents' center
423 to get the child's center. */
424 if (i%2 == 0){
425 center[k] -= width;
426 } else {
427 center[k] += width;
428 }
429 i = (i - i%2)/2;
430 }
431 return qt;
432
433}
434static QuadTree QuadTree_add_internal(QuadTree q, double *coord, double weight, int id, int level){
435 int i, dim = q->dim, ii;
436 node_data nd = NULL;
437
438 int max_level = q->max_level;
439 int idd;
440
441 /* Make sure that coord is within bounding box */
442 for (i = 0; i < q->dim; i++) {
443 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) {
444#ifdef DEBUG_PRINT
445 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),
446 (q->center[i] - q->width) - coord[i], coord[i]-(q->center[i] + q->width));
447#endif
448 //return NULL;
449 }
450 }
451
452 if (q->n == 0){
453 /* if this node is empty right now */
454 q->n = 1;
455 q->total_weight = weight;
456 q->average = gv_calloc(dim, sizeof(double));
457 for (i = 0; i < q->dim; i++) q->average[i] = coord[i];
458 nd = node_data_new(q->dim, weight, coord, id);
459 assert(!(q->l));
460 q->l = nd;
461 } else if (level < max_level){
462 /* otherwise open up into 2^dim quadtrees unless the level is too high */
463 q->total_weight += weight;
464 for (i = 0; i < q->dim; i++) q->average[i] = (q->average[i] * q->n + coord[i]) / (q->n + 1);
465 if (!q->qts){
466 q->qts = gv_calloc((size_t)1 << dim, sizeof(QuadTree));
467 }/* done adding new quadtree, now add points to them */
468
469 /* insert the old node (if exist) and the current node into the appropriate child quadtree */
470 ii = QuadTree_get_quadrant(dim, q->center, coord);
471 assert(ii < 1<<dim && ii >= 0);
472 if (q->qts[ii] == NULL) q->qts[ii] = QuadTree_new_in_quadrant(q->dim, q->center, q->width / 2, max_level, ii);
473
474 q->qts[ii] = QuadTree_add_internal(q->qts[ii], coord, weight, id, level + 1);
475 assert(q->qts[ii]);
476
477 if (q->l){
478 idd = q->l->id;
479 assert(q->n == 1);
480 coord = q->l->coord;
481 weight = q->l->node_weight;
482 ii = QuadTree_get_quadrant(dim, q->center, coord);
483 assert(ii < 1<<dim && ii >= 0);
484
485 if (q->qts[ii] == NULL) q->qts[ii] = QuadTree_new_in_quadrant(q->dim, q->center, (q->width)/2, max_level, ii);
486
487 q->qts[ii] = QuadTree_add_internal(q->qts[ii], coord, weight, idd, level + 1);
488 assert(q->qts[ii]);
489
490 /* delete the old node data on parent */
491 while (q->l != NULL) {
492 node_data next = q->l->next;
494 q->l = next;
495 }
496 }
497
498 q->n++;
499 } else {
500 assert(!(q->qts));
501 /* level is too high, append data in the linked list */
502 q->n++;
503 q->total_weight += weight;
504 for (i = 0; i < q->dim; i++) q->average[i] = (q->average[i] * q->n + coord[i]) / (q->n + 1);
505 nd = node_data_new(q->dim, weight, coord, id);
506 assert(q->l);
507 nd->next = q->l;
508 q->l = nd;
509 }
510 return q;
511}
512
513
514QuadTree QuadTree_add(QuadTree q, double *coord, double weight, int id){
515 if (!q) return q;
516 return QuadTree_add_internal(q, coord, weight, id, 0);
517
518}
519
520static void draw_polygon(FILE *fp, int dim, double *center, double width){
521 /* pliot the enclosing square */
522 if (dim < 2 || dim > 3) return;
523 fprintf(fp,"(*in c*){Line[{");
524
525 if (dim == 2){
526 fprintf(fp, "{%f, %f}", center[0] + width, center[1] + width);
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 } else if (dim == 3){
532 /* top */
533 fprintf(fp,"{");
534 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] + width);
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,"},");
540 /* bot */
541 fprintf(fp,"{");
542 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] - width);
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,"},");
548 /* for sides */
549 fprintf(fp,"{");
550 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] + width, center[2] - width);
551 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] + width, center[2] + width);
552 fprintf(fp,"},");
553
554 fprintf(fp,"{");
555 fprintf(fp, "{%f, %f, %f}", center[0] - width, center[1] + width, center[2] - width);
556 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] + width, center[2] + width);
557 fprintf(fp,"},");
558
559 fprintf(fp,"{");
560 fprintf(fp, "{%f, %f, %f}", center[0] + width, center[1] - width, center[2] - width);
561 fprintf(fp, ",{%f, %f, %f}", center[0] + width, center[1] - width, center[2] + width);
562 fprintf(fp,"},");
563
564 fprintf(fp,"{");
565 fprintf(fp, "{%f, %f, %f}", center[0] - width, center[1] - width, center[2] - width);
566 fprintf(fp, ",{%f, %f, %f}", center[0] - width, center[1] - width, center[2] + width);
567 fprintf(fp,"}");
568 }
569
570
571 fprintf(fp, "}]}(*end C*)");
572
573
574}
575static void QuadTree_print_internal(FILE *fp, QuadTree q, int level){
576 /* dump a quad tree in Mathematica format. */
577 node_data l, l0;
578 double *coord;
579 int i, dim;
580
581 if (!q) return;
582
583 draw_polygon(fp, q->dim, q->center, q->width);
584 dim = q->dim;
585
586 l0 = l = q->l;
587 if (l){
588 printf(",(*a*) {Red,");
589 while (l){
590 if (l != l0) printf(",");
591 coord = l->coord;
592 fprintf(fp, "(*node %d*) Point[{", l->id);
593 for (i = 0; i < dim; i++){
594 if (i != 0) printf(",");
595 fprintf(fp, "%f",coord[i]);
596 }
597 fprintf(fp, "}]");
598 l = l->next;
599 }
600 fprintf(fp, "}");
601 }
602
603 if (q->qts){
604 for (i = 0; i < 1<<dim; i++){
605 fprintf(fp, ",(*b*){");
606 QuadTree_print_internal(fp, q->qts[i], level + 1);
607 fprintf(fp, "}");
608 }
609 }
610
611
612}
613
614void QuadTree_print(FILE *fp, QuadTree q){
615 if (!fp) return;
616 if (q->dim == 2){
617 fprintf(fp, "Graphics[{");
618 } else if (q->dim == 3){
619 fprintf(fp, "Graphics3D[{");
620 } else {
621 return;
622 }
623 QuadTree_print_internal(fp, q, 0);
624 if (q->dim == 2){
625 fprintf(fp, "}, PlotRange -> All, Frame -> True, FrameTicks -> True]\n");
626 } else {
627 fprintf(fp, "}, PlotRange -> All]\n");
628 }
629}
630
631static void QuadTree_get_nearest_internal(QuadTree qt, double *x, double *y,
632 double *min, int *imin,
633 bool tentative) {
634 /* get the nearest point years to {x[0], ..., x[dim]} and store in y.*/
635 double *coord, dist;
636 int dim, i, iq = -1;
637 double qmin;
638
639 if (!qt) return;
640 dim = qt->dim;
641 node_data l = qt->l;
642 while (l){
643 coord = l->coord;
644 dist = point_distance(x, coord, dim);
645 if(*min < 0 || dist < *min) {
646 *min = dist;
647 *imin = l->id;
648 for (i = 0; i < dim; i++) y[i] = coord[i];
649 }
650 l = l->next;
651 }
652
653 if (qt->qts){
654 dist = point_distance(qt->center, x, dim);
655 if (*min >= 0 && (dist - sqrt((double) dim) * qt->width > *min)){
656 return;
657 } else {
658 if (tentative){/* quick first approximation*/
659 qmin = -1;
660 for (i = 0; i < 1<<dim; i++){
661 if (qt->qts[i]){
662 dist = point_distance(qt->qts[i]->average, x, dim);
663 if (dist < qmin || qmin < 0){
664 qmin = dist; iq = i;
665 }
666 }
667 }
668 assert(iq >= 0);
669 QuadTree_get_nearest_internal(qt->qts[iq], x, y, min, imin, tentative);
670 } else {
671 for (i = 0; i < 1<<dim; i++){
672 QuadTree_get_nearest_internal(qt->qts[i], x, y, min, imin, tentative);
673 }
674 }
675 }
676 }
677
678}
679
680
681void QuadTree_get_nearest(QuadTree qt, double *x, double *ymin, int *imin, double *min){
682
683 *min = -1;
684
685 QuadTree_get_nearest_internal(qt, x, ymin, min, imin, true);
686 QuadTree_get_nearest_internal(qt, x, ymin, min, imin, false);
687}
void QuadTree_get_nearest(QuadTree qt, double *x, double *ymin, int *imin, double *min)
Definition QuadTree.c:681
static void QuadTree_print_internal(FILE *fp, QuadTree q, int level)
Definition QuadTree.c:575
void QuadTree_get_repulsive_force(QuadTree qt, double *force, double *x, double bh, double p, double KP, double *counts)
Definition QuadTree.c:280
QuadTree QuadTree_add(QuadTree q, double *coord, double weight, int id)
Definition QuadTree.c:514
static void draw_polygon(FILE *fp, int dim, double *center, double width)
Definition QuadTree.c:520
QuadTree QuadTree_new_in_quadrant(int dim, double *center, double width, int max_level, int i)
Definition QuadTree.c:412
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:308
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:614
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:356
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:434
static void QuadTree_repulsive_force_accumulate(QuadTree qt, double *force, double *counts)
Definition QuadTree.c:241
static int QuadTree_get_quadrant(int dim, double *center, double *coord)
Definition QuadTree.c:395
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:374
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:631
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:80
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:149
static uint64_t id
Definition gv2gml.c:42
static int imin(int a, int b)
minimum of two integers
Definition gv_math.h:27
pointf coord(node_t *n)
Definition utils.c:151
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)