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