Parse floating-point values without leading 0 correctly
[geda-pcb/whiteaudio.git] / gts / bbtree.c
blobcec93e4cf610c464dd4fdbcb11e5bc326e427dd1
1 /* GTS - Library for the manipulation of triangulated surfaces
2 * Copyright (C) 1999 Stéphane Popinet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include <math.h>
21 #include "gts.h"
23 static void bbox_init (GtsBBox * bbox)
25 bbox->bounded = NULL;
28 /**
29 * gts_bbox_class:
31 * Returns: the #GtsBBoxClass.
33 GtsBBoxClass * gts_bbox_class (void)
35 static GtsBBoxClass * klass = NULL;
37 if (klass == NULL) {
38 GtsObjectClassInfo bbox_info = {
39 "GtsBBox",
40 sizeof (GtsBBox),
41 sizeof (GtsBBoxClass),
42 (GtsObjectClassInitFunc) NULL,
43 (GtsObjectInitFunc) bbox_init,
44 (GtsArgSetFunc) NULL,
45 (GtsArgGetFunc) NULL
47 klass = gts_object_class_new (gts_object_class (), &bbox_info);
50 return klass;
53 /**
54 * gts_bbox_set:
55 * @bbox: a #GtsBBox.
56 * @bounded: the object to be bounded.
57 * @x1: x-coordinate of the lower left corner.
58 * @y1: y-coordinate of the lower left corner.
59 * @z1: z-coordinate of the lower left corner.
60 * @x2: x-coordinate of the upper right corner.
61 * @y2: y-coordinate of the upper right corner.
62 * @z2: z-coordinate of the upper right corner.
64 * Sets fields of @bbox.
66 void gts_bbox_set (GtsBBox * bbox,
67 gpointer bounded,
68 gdouble x1, gdouble y1, gdouble z1,
69 gdouble x2, gdouble y2, gdouble z2)
71 g_return_if_fail (bbox != NULL);
72 g_return_if_fail (x2 >= x1 && y2 >= y1 && z2 >= z1);
74 bbox->x1 = x1; bbox->y1 = y1; bbox->z1 = z1;
75 bbox->x2 = x2; bbox->y2 = y2; bbox->z2 = z2;
76 bbox->bounded = bounded;
79 /**
80 * gts_bbox_new:
81 * @klass: a #GtsBBoxClass.
82 * @bounded: the object to be bounded.
83 * @x1: x-coordinate of the lower left corner.
84 * @y1: y-coordinate of the lower left corner.
85 * @z1: z-coordinate of the lower left corner.
86 * @x2: x-coordinate of the upper right corner.
87 * @y2: y-coordinate of the upper right corner.
88 * @z2: z-coordinate of the upper right corner.
90 * Returns: a new #GtsBBox.
92 GtsBBox * gts_bbox_new (GtsBBoxClass * klass,
93 gpointer bounded,
94 gdouble x1, gdouble y1, gdouble z1,
95 gdouble x2, gdouble y2, gdouble z2)
97 GtsBBox * bbox;
99 g_return_val_if_fail (klass != NULL, NULL);
101 bbox = GTS_BBOX (gts_object_new (GTS_OBJECT_CLASS (klass)));
102 gts_bbox_set (bbox, bounded, x1, y1, z1, x2, y2, z2);
103 return bbox;
107 * gts_bbox_triangle:
108 * @klass: a #GtsBBoxClass.
109 * @t: a #GtsTriangle.
111 * Returns: a new #GtsBBox bounding box of @t.
113 GtsBBox * gts_bbox_triangle (GtsBBoxClass * klass,
114 GtsTriangle * t)
116 GtsBBox * bbox;
117 GtsPoint * p;
119 g_return_val_if_fail (t != NULL, NULL);
120 g_return_val_if_fail (klass != NULL, NULL);
122 p = GTS_POINT (GTS_SEGMENT (t->e1)->v1);
123 bbox = gts_bbox_new (klass, t, p->x, p->y, p->z, p->x, p->y, p->z);
125 p = GTS_POINT (GTS_SEGMENT (t->e1)->v2);
126 if (p->x > bbox->x2) bbox->x2 = p->x;
127 if (p->x < bbox->x1) bbox->x1 = p->x;
128 if (p->y > bbox->y2) bbox->y2 = p->y;
129 if (p->y < bbox->y1) bbox->y1 = p->y;
130 if (p->z > bbox->z2) bbox->z2 = p->z;
131 if (p->z < bbox->z1) bbox->z1 = p->z;
132 p = GTS_POINT (gts_triangle_vertex (t));
133 if (p->x > bbox->x2) bbox->x2 = p->x;
134 if (p->x < bbox->x1) bbox->x1 = p->x;
135 if (p->y > bbox->y2) bbox->y2 = p->y;
136 if (p->y < bbox->y1) bbox->y1 = p->y;
137 if (p->z > bbox->z2) bbox->z2 = p->z;
138 if (p->z < bbox->z1) bbox->z1 = p->z;
140 return bbox;
144 * gts_bbox_segment:
145 * @klass: a #GtsBBoxClass.
146 * @s: a #GtsSegment.
148 * Returns: a new #GtsBBox bounding box of @s.
150 GtsBBox * gts_bbox_segment (GtsBBoxClass * klass, GtsSegment * s)
152 GtsBBox * bbox;
153 GtsPoint * p1, * p2;
155 g_return_val_if_fail (s != NULL, NULL);
156 g_return_val_if_fail (klass != NULL, NULL);
158 bbox = gts_bbox_new (klass, s, 0., 0., 0., 0., 0., 0.);
160 p1 = GTS_POINT (s->v1);
161 p2 = GTS_POINT (s->v2);
162 if (p1->x > p2->x) {
163 bbox->x2 = p1->x; bbox->x1 = p2->x;
165 else {
166 bbox->x1 = p1->x; bbox->x2 = p2->x;
168 if (p1->y > p2->y) {
169 bbox->y2 = p1->y; bbox->y1 = p2->y;
171 else {
172 bbox->y1 = p1->y; bbox->y2 = p2->y;
174 if (p1->z > p2->z) {
175 bbox->z2 = p1->z; bbox->z1 = p2->z;
177 else {
178 bbox->z1 = p1->z; bbox->z2 = p2->z;
181 return bbox;
184 static void bbox_foreach_vertex (GtsPoint * p, GtsBBox * bb)
186 if (p->x < bb->x1) bb->x1 = p->x;
187 if (p->y < bb->y1) bb->y1 = p->y;
188 if (p->z < bb->z1) bb->z1 = p->z;
189 if (p->x > bb->x2) bb->x2 = p->x;
190 if (p->y > bb->y2) bb->y2 = p->y;
191 if (p->z > bb->z2) bb->z2 = p->z;
195 * gts_bbox_surface:
196 * @klass: a #GtsBBoxClass.
197 * @surface: a #GtsSurface.
199 * Returns: a new #GtsBBox bounding box of @surface.
201 GtsBBox * gts_bbox_surface (GtsBBoxClass * klass, GtsSurface * surface)
203 GtsBBox * bbox;
205 g_return_val_if_fail (klass != NULL, NULL);
206 g_return_val_if_fail (surface != NULL, NULL);
208 bbox = gts_bbox_new (klass, surface, 0., 0., 0., 0., 0., 0.);
209 bbox->x1 = bbox->y1 = bbox->z1 = G_MAXDOUBLE;
210 bbox->x2 = bbox->y2 = bbox->z2 = -G_MAXDOUBLE;
212 gts_surface_foreach_vertex (surface, (GtsFunc) bbox_foreach_vertex, bbox);
214 return bbox;
218 * gts_bbox_bboxes:
219 * @klass: a #GtsBBoxClass.
220 * @bboxes: a list of #GtsBBox.
222 * Returns: a new #GtsBBox bounding box of all the bounding boxes in
223 * @bboxes.
225 GtsBBox * gts_bbox_bboxes (GtsBBoxClass * klass, GSList * bboxes)
227 GtsBBox * bbox;
228 GtsBBox * bb;
230 g_return_val_if_fail (bboxes != NULL, NULL);
231 g_return_val_if_fail (klass != NULL, NULL);
233 bb = bboxes->data;
234 bbox = gts_bbox_new (klass, bboxes,
235 bb->x1, bb->y1, bb->z1, bb->x2, bb->y2, bb->z2);
236 bboxes = bboxes->next;
237 while (bboxes) {
238 bb = bboxes->data;
239 if (bb->x1 < bbox->x1) bbox->x1 = bb->x1;
240 if (bb->y1 < bbox->y1) bbox->y1 = bb->y1;
241 if (bb->z1 < bbox->z1) bbox->z1 = bb->z1;
242 if (bb->x2 > bbox->x2) bbox->x2 = bb->x2;
243 if (bb->y2 > bbox->y2) bbox->y2 = bb->y2;
244 if (bb->z2 > bbox->z2) bbox->z2 = bb->z2;
245 bboxes = bboxes->next;
248 return bbox;
252 * gts_bbox_points:
253 * @klass: a #GtsBBoxClass.
254 * @points: a list of #GtsPoint.
256 * Returns: a new #GtsBBox bounding box of @points.
258 GtsBBox * gts_bbox_points (GtsBBoxClass * klass, GSList * points)
260 GtsPoint * p;
261 GtsBBox * bbox;
262 GSList * i;
264 if (points == NULL)
265 return NULL;
267 p = points->data;
268 bbox = gts_bbox_new (klass, points, p->x, p->y, p->z, p->x, p->y, p->z);
270 i = points->next;
271 while (i) {
272 p = i->data;
273 if (p->x > bbox->x2)
274 bbox->x2 = p->x;
275 else if (p->x < bbox->x1)
276 bbox->x1 = p->x;
277 if (p->y > bbox->y2)
278 bbox->y2 = p->y;
279 else if (p->y < bbox->y1)
280 bbox->y1 = p->y;
281 if (p->z > bbox->z2)
282 bbox->z2 = p->z;
283 else if (p->z < bbox->z1)
284 bbox->z1 = p->z;
285 i = i->next;
288 return bbox;
292 * gts_bboxes_are_overlapping:
293 * @bb1: a #GtsBBox.
294 * @bb2: a #GtsBBox.
296 * Returns: %TRUE if the bounding boxes @bb1 and @bb2 are overlapping
297 * (including just touching), %FALSE otherwise.
299 gboolean gts_bboxes_are_overlapping (GtsBBox * bb1, GtsBBox * bb2)
301 if (bb1 == bb2)
302 return TRUE;
303 if (bb1->x1 > bb2->x2)
304 return FALSE;
305 if (bb2->x1 > bb1->x2)
306 return FALSE;
307 if (bb1->y1 > bb2->y2)
308 return FALSE;
309 if (bb2->y1 > bb1->y2)
310 return FALSE;
311 if (bb1->z1 > bb2->z2)
312 return FALSE;
313 if (bb2->z1 > bb1->z2)
314 return FALSE;
315 return TRUE;
318 #define bbox_volume(bb) (((bb)->x2 -\
319 (bb)->x1)*\
320 ((bb)->y2 -\
321 (bb)->y1)*\
322 ((bb)->z2 -\
323 (bb)->z1))
326 * gts_bbox_diagonal2:
327 * @bb: a #GtsBBox.
329 * Returns: the squared length of the diagonal of @bb.
331 gdouble gts_bbox_diagonal2 (GtsBBox * bb)
333 gdouble x, y, z;
335 g_return_val_if_fail (bb != NULL, 0.);
337 x = bb->x2 - bb->x1;
338 y = bb->y2 - bb->y1;
339 z = bb->z2 - bb->z1;
341 return x*x + y*y + z*z;
345 * gts_bbox_draw:
346 * @bb: a #GtsBBox.
347 * @fptr: a file pointer.
349 * Writes in file @fptr an OOGL (Geomview) description of @bb.
351 void gts_bbox_draw (GtsBBox * bb, FILE * fptr)
353 g_return_if_fail (bb != NULL);
355 fprintf (fptr, "OFF 8 6 12\n");
356 fprintf (fptr, "%g %g %g\n",
357 bb->x1, bb->y1, bb->z1);
358 fprintf (fptr, "%g %g %g\n",
359 bb->x2, bb->y1, bb->z1);
360 fprintf (fptr, "%g %g %g\n",
361 bb->x2, bb->y2, bb->z1);
362 fprintf (fptr, "%g %g %g\n",
363 bb->x1, bb->y2, bb->z1);
364 fprintf (fptr, "%g %g %g\n",
365 bb->x1, bb->y1, bb->z2);
366 fprintf (fptr, "%g %g %g\n",
367 bb->x2, bb->y1, bb->z2);
368 fprintf (fptr, "%g %g %g\n",
369 bb->x2, bb->y2, bb->z2);
370 fprintf (fptr, "%g %g %g\n",
371 bb->x1, bb->y2, bb->z2);
372 fputs ("4 3 2 1 0\n"
373 "4 4 5 6 7\n"
374 "4 2 3 7 6\n"
375 "4 0 1 5 4\n"
376 "4 0 4 7 3\n"
377 "4 1 2 6 5\n",
378 fptr);
381 #define MINMAX(x1, x2, xmin, xmax) { if (x1 < x2) { xmin = x1; xmax = x2; }\
382 else { xmin = x2; xmax = x1; } }
385 * gts_bbox_point_distance2:
386 * @bb: a #GtsBBox.
387 * @p: a #GtsPoint.
388 * @min: a pointer on a gdouble.
389 * @max: a pointer on a gdouble.
391 * Sets @min and @max to lower and upper bounds for the square of the
392 * Euclidean distance between the object contained in @bb and @p. For these
393 * bounds to make any sense the bounding box must be "tight" i.e. each of the
394 * 6 faces of the box must at least be touched by one point of the bounded
395 * object.
397 void gts_bbox_point_distance2 (GtsBBox * bb, GtsPoint * p,
398 gdouble * min, gdouble * max)
400 gdouble x1, y1, z1, x2, y2, z2, x, y, z;
401 gdouble dmin, dmax, xd1, xd2, yd1, yd2, zd1, zd2;
402 gdouble mx, Mx, my, My, mz, Mz;
404 g_return_if_fail (bb != NULL);
405 g_return_if_fail (p != NULL);
406 g_return_if_fail (min != NULL);
407 g_return_if_fail (max != NULL);
409 x1 = bb->x1; y1 = bb->y1; z1 = bb->z1;
410 x2 = bb->x2; y2 = bb->y2; z2 = bb->z2;
411 x = p->x; y = p->y; z = p->z;
413 xd1 = (x1 - x)*(x1 - x);
414 xd2 = (x - x2)*(x - x2);
415 yd1 = (y1 - y)*(y1 - y);
416 yd2 = (y - y2)*(y - y2);
417 zd1 = (z1 - z)*(z1 - z);
418 zd2 = (z - z2)*(z - z2);
420 dmin = x < x1 ? xd1 : x > x2 ? xd2 : 0.0;
421 dmin += y < y1 ? yd1 : y > y2 ? yd2 : 0.0;
422 dmin += z < z1 ? zd1 : z > z2 ? zd2 : 0.0;
424 MINMAX (xd1, xd2, mx, Mx);
425 MINMAX (yd1, yd2, my, My);
426 MINMAX (zd1, zd2, mz, Mz);
428 dmax = mx + My + Mz;
429 dmax = MIN (dmax, Mx + my + Mz);
430 dmax = MIN (dmax, Mx + My + mz);
432 *min = dmin;
433 *max = dmax;
437 * gts_bbox_is_stabbed:
438 * @bb: a #GtsBBox.
439 * @p: a #GtsPoint.
441 * Returns: %TRUE if the ray starting at @p and ending at (+infty,
442 * @p->y, @p->z) intersects with @bb, %FALSE otherwise.
444 gboolean gts_bbox_is_stabbed (GtsBBox * bb, GtsPoint * p)
446 g_return_val_if_fail (bb != NULL, FALSE);
447 g_return_val_if_fail (p != NULL, FALSE);
449 if (p->x > bb->x2 ||
450 p->y < bb->y1 || p->y > bb->y2 ||
451 p->z < bb->z1 || p->z > bb->z2)
452 return FALSE;
453 return TRUE;
456 extern int triBoxOverlap (double boxcenter[3],
457 double boxhalfsize[3],
458 double triverts[3][3]);
461 * gts_bbox_overlaps_triangle:
462 * @bb: a #GtsBBox.
463 * @t: a #GtsTriangle.
465 * This is a wrapper around the fast overlap test of Tomas
466 * Akenine-Moller (http://www.cs.lth.se/home/Tomas_Akenine_Moller/).
468 * Returns: %TRUE if @bb overlaps with @t, %FALSE otherwise.
470 gboolean gts_bbox_overlaps_triangle (GtsBBox * bb, GtsTriangle * t)
472 double bc[3], bh[3], tv[3][3];
473 GtsPoint * p1, * p2, * p3;
475 g_return_val_if_fail (bb != NULL, FALSE);
476 g_return_val_if_fail (t != NULL, FALSE);
478 bc[0] = (bb->x2 + bb->x1)/2.;
479 bh[0] = (bb->x2 - bb->x1)/2.;
480 bc[1] = (bb->y2 + bb->y1)/2.;
481 bh[1] = (bb->y2 - bb->y1)/2.;
482 bc[2] = (bb->z2 + bb->z1)/2.;
483 bh[2] = (bb->z2 - bb->z1)/2.;
484 p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1);
485 p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2);
486 p3 = GTS_POINT (gts_triangle_vertex (t));
487 tv[0][0] = p1->x; tv[0][1] = p1->y; tv[0][2] = p1->z;
488 tv[1][0] = p2->x; tv[1][1] = p2->y; tv[1][2] = p2->z;
489 tv[2][0] = p3->x; tv[2][1] = p3->y; tv[2][2] = p3->z;
491 return triBoxOverlap (bc, bh, tv);
495 * gts_bbox_overlaps_segment:
496 * @bb: a #GtsBBox.
497 * @s: a #GtsSegment.
499 * This functions uses gts_bbox_overlaps_triangle() with a degenerate
500 * triangle.
502 * Returns: %TRUE if @bb overlaps with @s, %FALSE otherwise.
504 gboolean gts_bbox_overlaps_segment (GtsBBox * bb, GtsSegment * s)
506 double bc[3], bh[3], tv[3][3];
507 GtsPoint * p1, * p2, * p3;
509 g_return_val_if_fail (bb != NULL, FALSE);
510 g_return_val_if_fail (s != NULL, FALSE);
512 bc[0] = (bb->x2 + bb->x1)/2.;
513 bh[0] = (bb->x2 - bb->x1)/2.;
514 bc[1] = (bb->y2 + bb->y1)/2.;
515 bh[1] = (bb->y2 - bb->y1)/2.;
516 bc[2] = (bb->z2 + bb->z1)/2.;
517 bh[2] = (bb->z2 - bb->z1)/2.;
518 p1 = GTS_POINT (s->v1);
519 p2 = GTS_POINT (s->v2);
520 p3 = p1;
521 tv[0][0] = p1->x; tv[0][1] = p1->y; tv[0][2] = p1->z;
522 tv[1][0] = p2->x; tv[1][1] = p2->y; tv[1][2] = p2->z;
523 tv[2][0] = p3->x; tv[2][1] = p3->y; tv[2][2] = p3->z;
525 return triBoxOverlap (bc, bh, tv);
529 * gts_bb_tree_new:
530 * @bboxes: a list of #GtsBBox.
532 * Builds a new hierarchy of bounding boxes for @bboxes. At each
533 * level, the GNode->data field contains a #GtsBBox bounding box of
534 * all the children. The tree is binary and is built by repeatedly
535 * cutting in two approximately equal halves the bounding boxes at
536 * each level until a leaf node (i.e. a bounding box given in @bboxes)
537 * is reached. In order to minimize the depth of the tree, the cutting
538 * direction is always chosen as perpendicular to the longest
539 * dimension of the bounding box.
541 * Returns: a new hierarchy of bounding boxes.
543 GNode * gts_bb_tree_new (GSList * bboxes)
545 GSList * i, * positive = NULL, * negative = NULL;
546 GNode * node;
547 GtsBBox * bbox;
548 guint dir, np = 0, nn = 0;
549 gdouble * p1, * p2;
550 gdouble cut;
552 g_return_val_if_fail (bboxes != NULL, NULL);
554 if (bboxes->next == NULL) /* leaf node */
555 return g_node_new (bboxes->data);
557 bbox = gts_bbox_bboxes (gts_bbox_class (), bboxes);
558 node = g_node_new (bbox);
560 if (bbox->x2 - bbox->x1 > bbox->y2 - bbox->y1) {
561 if (bbox->z2 - bbox->z1 > bbox->x2 - bbox->x1)
562 dir = 2;
563 else
564 dir = 0;
566 else if (bbox->z2 - bbox->z1 > bbox->y2 - bbox->y1)
567 dir = 2;
568 else
569 dir = 1;
571 p1 = (gdouble *) &bbox->x1;
572 p2 = (gdouble *) &bbox->x2;
573 cut = (p1[dir] + p2[dir])/2.;
574 i = bboxes;
575 while (i) {
576 bbox = i->data;
577 p1 = (gdouble *) &bbox->x1;
578 p2 = (gdouble *) &bbox->x2;
579 if ((p1[dir] + p2[dir])/2. > cut) {
580 positive = g_slist_prepend (positive, bbox);
581 np++;
583 else {
584 negative = g_slist_prepend (negative, bbox);
585 nn++;
587 i = i->next;
589 if (!positive) {
590 GSList * last = g_slist_nth (negative, (nn - 1)/2);
591 positive = last->next;
592 last->next = NULL;
594 else if (!negative) {
595 GSList * last = g_slist_nth (positive, (np - 1)/2);
596 negative = last->next;
597 last->next = NULL;
599 g_node_prepend (node, gts_bb_tree_new (positive));
600 g_slist_free (positive);
601 g_node_prepend (node, gts_bb_tree_new (negative));
602 g_slist_free (negative);
604 return node;
607 static void prepend_triangle_bbox (GtsTriangle * t, GSList ** bboxes)
609 *bboxes = g_slist_prepend (*bboxes,
610 gts_bbox_triangle (gts_bbox_class (), t));
614 * gts_bb_tree_surface:
615 * @s: a #GtsSurface.
617 * Returns: a new hierarchy of bounding boxes bounding the faces of @s.
619 GNode * gts_bb_tree_surface (GtsSurface * s)
621 GSList * bboxes = NULL;
622 GNode * tree;
624 g_return_val_if_fail (s != NULL, NULL);
626 gts_surface_foreach_face (s, (GtsFunc) prepend_triangle_bbox, &bboxes);
627 tree = gts_bb_tree_new (bboxes);
628 g_slist_free (bboxes);
630 return tree;
634 * gts_bb_tree_stabbed:
635 * @tree: a bounding box tree.
636 * @p: a #GtsPoint.
638 * Returns: a list of bounding boxes, leaves of @tree which are
639 * stabbed by the ray defined by @p (see gts_bbox_is_stabbed()).
641 GSList * gts_bb_tree_stabbed (GNode * tree, GtsPoint * p)
643 GSList * list = NULL;
644 GtsBBox * bb;
645 GNode * i;
647 g_return_val_if_fail (tree != NULL, NULL);
648 g_return_val_if_fail (p != NULL, NULL);
650 bb = tree->data;
651 if (!gts_bbox_is_stabbed (bb, p))
652 return NULL;
653 if (tree->children == NULL) /* leaf node */
654 return g_slist_prepend (NULL, bb);
655 i = tree->children;
656 while (i) {
657 list = g_slist_concat (list, gts_bb_tree_stabbed (i, p));
658 i = i->next;
660 return list;
664 * gts_bb_tree_overlap:
665 * @tree: a bounding box tree.
666 * @bbox: a #GtsBBox.
668 * Returns: a list of bounding boxes, leaves of @tree which overlap @bbox.
670 GSList * gts_bb_tree_overlap (GNode * tree, GtsBBox * bbox)
672 GSList * list = NULL;
673 GtsBBox * bb;
674 GNode * i;
676 g_return_val_if_fail (tree != NULL, NULL);
677 g_return_val_if_fail (bbox != NULL, NULL);
679 bb = tree->data;
680 if (!gts_bboxes_are_overlapping (bbox, bb))
681 return NULL;
682 if (tree->children == NULL) /* leaf node */
683 return g_slist_prepend (NULL, bb);
684 i = tree->children;
685 while (i) {
686 list = g_slist_concat (list, gts_bb_tree_overlap (i, bbox));
687 i = i->next;
689 return list;
693 * gts_bb_tree_is_overlapping:
694 * @tree: a bounding box tree.
695 * @bbox: a #GtsBBox.
697 * Returns: %TRUE if any leaf of @tree overlaps @bbox, %FALSE otherwise.
699 gboolean gts_bb_tree_is_overlapping (GNode * tree, GtsBBox * bbox)
701 GtsBBox * bb;
702 GNode * i;
704 g_return_val_if_fail (tree != NULL, FALSE);
705 g_return_val_if_fail (bbox != NULL, FALSE);
707 bb = tree->data;
708 if (!gts_bboxes_are_overlapping (bbox, bb))
709 return FALSE;
710 if (tree->children == NULL) /* leaf node */
711 return TRUE;
712 i = tree->children;
713 while (i) {
714 if (gts_bb_tree_is_overlapping (i, bbox))
715 return TRUE;
716 i = i->next;
718 return FALSE;
722 * gts_bb_tree_traverse_overlapping:
723 * @tree1: a bounding box tree.
724 * @tree2: a bounding box tree.
725 * @func: a #GtsBBTreeTraverseFunc.
726 * @data: user data to be passed to @func.
728 * Calls @func for each overlapping pair of leaves of @tree1 and @tree2.
730 void gts_bb_tree_traverse_overlapping (GNode * tree1, GNode * tree2,
731 GtsBBTreeTraverseFunc func,
732 gpointer data)
734 GtsBBox * bb1, * bb2;
736 g_return_if_fail (tree1 != NULL && tree2 != NULL);
738 bb1 = tree1->data; bb2 = tree2->data;
739 if (!gts_bboxes_are_overlapping (bb1, bb2))
740 return;
742 if (tree1->children == NULL && tree2->children == NULL)
743 (*func) (tree1->data, tree2->data, data);
744 else if (tree2->children == NULL ||
745 (tree1->children != NULL &&
746 bbox_volume (bb1) > bbox_volume (bb2))) {
747 GNode * i = tree1->children;
748 while (i) {
749 gts_bb_tree_traverse_overlapping (i, tree2, func, data);
750 i = i->next;
753 else {
754 GNode * i = tree2->children;
755 while (i) {
756 gts_bb_tree_traverse_overlapping (tree1, i, func, data);
757 i = i->next;
763 * gts_bb_tree_draw:
764 * @tree: a bounding box tree.
765 * @depth: a specified depth.
766 * @fptr: a file pointer.
768 * Write in @fptr an OOGL (Geomview) description of @tree for the
769 * depth specified by @depth.
771 void gts_bb_tree_draw (GNode * tree, guint depth, FILE * fptr)
773 guint d;
775 g_return_if_fail (tree != NULL);
776 g_return_if_fail (fptr != NULL);
778 d = g_node_depth (tree);
780 if (d == 1)
781 fprintf (fptr, "{ LIST");
783 if (d == depth)
784 gts_bbox_draw (tree->data, fptr);
785 else if (d < depth) {
786 GNode * i = tree->children;
787 while (i) {
788 gts_bb_tree_draw (i, depth, fptr);
789 i = i->next;
793 if (d == 1)
794 fprintf (fptr, "}\n");
797 static void bb_tree_free (GNode * tree, gboolean free_leaves)
799 GNode * i;
801 g_return_if_fail (tree != NULL);
803 if (!free_leaves && tree->children == NULL) /* leaf node */
804 return;
806 gts_object_destroy (tree->data);
808 i = tree->children;
809 while (i) {
810 bb_tree_free (i, free_leaves);
811 i = i->next;
816 * gts_bb_tree_destroy:
817 * @tree: a bounding box tree.
818 * @free_leaves: if %TRUE the bounding boxes given by the user are freed.
820 * Destroys all the bounding boxes created by @tree and destroys the
821 * tree itself. If @free_leaves is set to %TRUE, destroys boxes given
822 * by the user when creating the tree (i.e. leaves of the tree).
824 void gts_bb_tree_destroy (GNode * tree, gboolean free_leaves)
826 g_return_if_fail (tree != NULL);
828 bb_tree_free (tree, free_leaves);
829 g_node_destroy (tree);
832 static gdouble bb_tree_min_max (GNode * tree,
833 GtsPoint * p,
834 gdouble min_max,
835 GSList ** list)
837 GNode * tree1, * tree2;
838 gdouble min1, max1, min2, max2;
840 if (tree->children == NULL) {
841 *list = g_slist_prepend (*list, tree->data);
842 return min_max;
844 tree1 = tree->children;
845 gts_bbox_point_distance2 (tree1->data, p, &min1, &max1);
846 if (max1 < min_max)
847 min_max = max1;
849 tree2 = tree1->next;
850 gts_bbox_point_distance2 (tree2->data, p, &min2, &max2);
851 if (max2 < min_max)
852 min_max = max2;
854 if (min1 < min2) {
855 if (min1 <= min_max) {
856 min_max = bb_tree_min_max (tree1, p, min_max, list);
857 if (min2 <= min_max)
858 min_max = bb_tree_min_max (tree2, p, min_max, list);
861 else {
862 if (min2 <= min_max) {
863 min_max = bb_tree_min_max (tree2, p, min_max, list);
864 if (min1 <= min_max)
865 min_max = bb_tree_min_max (tree1, p, min_max, list);
869 return min_max;
873 * gts_bb_tree_point_closest_bboxes:
874 * @tree: a bounding box tree.
875 * @p: a #GtsPoint.
877 * Returns: a list of #GtsBBox. One of the bounding boxes is assured to contain
878 * the object of @tree closest to @p.
880 GSList * gts_bb_tree_point_closest_bboxes (GNode * tree,
881 GtsPoint * p)
883 gdouble min, min_max;
884 GSList * list = NULL, * i, * prev = NULL;
886 g_return_val_if_fail (tree != NULL, NULL);
887 g_return_val_if_fail (p != NULL, NULL);
889 gts_bbox_point_distance2 (tree->data, p, &min, &min_max);
890 min_max = bb_tree_min_max (tree, p, min_max, &list);
892 i = list;
893 while (i) {
894 GSList * next = i->next;
895 gdouble min, max;
897 gts_bbox_point_distance2 (i->data, p, &min, &max);
899 if (min > min_max) {
900 if (prev == NULL)
901 list = next;
902 else
903 prev->next = next;
904 g_slist_free_1 (i);
906 else
907 prev = i;
908 i = next;
911 return list;
915 * gts_bb_tree_point_distance:
916 * @tree: a bounding box tree.
917 * @p: a #GtsPoint.
918 * @distance: a #GtsBBoxDistFunc.
919 * @bbox: if not %NULL is set to the bounding box containing the closest
920 * object.
922 * Returns: the distance as evaluated by @distance between @p and the closest
923 * object in @tree.
925 gdouble gts_bb_tree_point_distance (GNode * tree,
926 GtsPoint * p,
927 GtsBBoxDistFunc distance,
928 GtsBBox ** bbox)
930 GSList * list, * i;
931 gdouble dmin = G_MAXDOUBLE;
933 g_return_val_if_fail (tree != NULL, dmin);
934 g_return_val_if_fail (p != NULL, dmin);
935 g_return_val_if_fail (distance != NULL, dmin);
937 i = list = gts_bb_tree_point_closest_bboxes (tree, p);
938 while (i) {
939 gdouble d = (*distance) (p, GTS_BBOX (i->data)->bounded);
941 if (fabs (d) < fabs (dmin)) {
942 dmin = d;
943 if (bbox)
944 *bbox = i->data;
946 i = i->next;
948 g_slist_free (list);
950 return dmin;
954 * gts_bb_tree_point_closest:
955 * @tree: a bounding box tree.
956 * @p: a #GtsPoint.
957 * @closest: a #GtsBBoxClosestFunc.
958 * @distance: if not %NULL is set to the distance between @p and the
959 * new #GtsPoint.
961 * Returns: a new #GtsPoint, closest point to @p and belonging to an object of
962 * @tree.
964 GtsPoint * gts_bb_tree_point_closest (GNode * tree,
965 GtsPoint * p,
966 GtsBBoxClosestFunc closest,
967 gdouble * distance)
969 GSList * list, * i;
970 gdouble dmin = G_MAXDOUBLE;
971 GtsPoint * np = NULL;
973 g_return_val_if_fail (tree != NULL, NULL);
974 g_return_val_if_fail (p != NULL, NULL);
975 g_return_val_if_fail (closest != NULL, NULL);
977 i = list = gts_bb_tree_point_closest_bboxes (tree, p);
978 while (i) {
979 GtsPoint * tp = (*closest) (p, GTS_BBOX (i->data)->bounded);
980 gdouble d = gts_point_distance2 (tp, p);
982 if (d < dmin) {
983 if (np)
984 gts_object_destroy (GTS_OBJECT (np));
985 np = tp;
986 dmin = d;
988 else
989 gts_object_destroy (GTS_OBJECT (tp));
990 i = i->next;
992 g_slist_free (list);
994 if (distance)
995 *distance = dmin;
997 return np;
1001 * gts_bb_tree_triangle_distance:
1002 * @tree: a bounding box tree.
1003 * @t: a #GtsTriangle.
1004 * @distance: a #GtsBBoxDistFunc.
1005 * @delta: spatial scale of the sampling to be used.
1006 * @range: a #GtsRange to be filled with the results.
1008 * Given a triangle @t, points are sampled regularly on its surface
1009 * using @delta as increment. The distance from each of these points
1010 * to the closest object of @tree is computed using @distance and the
1011 * gts_bb_tree_point_distance() function. The fields of @range are
1012 * filled with the number of points sampled, the minimum, average and
1013 * maximum value and the standard deviation.
1015 void gts_bb_tree_triangle_distance (GNode * tree,
1016 GtsTriangle * t,
1017 GtsBBoxDistFunc distance,
1018 gdouble delta,
1019 GtsRange * range)
1021 GtsPoint * p1, * p2, * p3, * p;
1022 GtsVector p1p2, p1p3;
1023 gdouble l1, t1, dt1;
1024 guint i, n1;
1026 g_return_if_fail (tree != NULL);
1027 g_return_if_fail (t != NULL);
1028 g_return_if_fail (distance != NULL);
1029 g_return_if_fail (delta > 0.);
1030 g_return_if_fail (range != NULL);
1032 gts_triangle_vertices (t,
1033 (GtsVertex **) &p1,
1034 (GtsVertex **) &p2,
1035 (GtsVertex **) &p3);
1037 gts_vector_init (p1p2, p1, p2);
1038 gts_vector_init (p1p3, p1, p3);
1039 gts_range_init (range);
1040 p = GTS_POINT (gts_object_new (GTS_OBJECT_CLASS (gts_point_class ())));
1042 l1 = sqrt (gts_vector_scalar (p1p2, p1p2));
1043 n1 = l1/delta + 1;
1044 dt1 = 1.0/(gdouble) n1;
1045 t1 = 0.0;
1046 for (i = 0; i <= n1; i++, t1 += dt1) {
1047 gdouble t2 = 1. - t1;
1048 gdouble x = t2*p1p3[0];
1049 gdouble y = t2*p1p3[1];
1050 gdouble z = t2*p1p3[2];
1051 gdouble l2 = sqrt (x*x + y*y + z*z);
1052 guint j, n2 = (guint) (l2/delta + 1);
1053 gdouble dt2 = t2/(gdouble) n2;
1055 x = t2*p1->x + t1*p2->x;
1056 y = t2*p1->y + t1*p2->y;
1057 z = t2*p1->z + t1*p2->z;
1059 t2 = 0.0;
1060 for (j = 0; j <= n2; j++, t2 += dt2) {
1061 p->x = x + t2*p1p3[0];
1062 p->y = y + t2*p1p3[1];
1063 p->z = z + t2*p1p3[2];
1065 gts_range_add_value (range,
1066 gts_bb_tree_point_distance (tree, p, distance, NULL));
1070 gts_object_destroy (GTS_OBJECT (p));
1071 gts_range_update (range);
1075 * gts_bb_tree_segment_distance:
1076 * @tree: a bounding box tree.
1077 * @s: a #GtsSegment.
1078 * @distance: a #GtsBBoxDistFunc.
1079 * @delta: spatial scale of the sampling to be used.
1080 * @range: a #GtsRange to be filled with the results.
1082 * Given a segment @s, points are sampled regularly on its length
1083 * using @delta as increment. The distance from each of these points
1084 * to the closest object of @tree is computed using @distance and the
1085 * gts_bb_tree_point_distance() function. The fields of @range are
1086 * filled with the number of points sampled, the minimum, average and
1087 * maximum value and the standard deviation.
1089 void gts_bb_tree_segment_distance (GNode * tree,
1090 GtsSegment * s,
1091 gdouble (*distance) (GtsPoint *,
1092 gpointer),
1093 gdouble delta,
1094 GtsRange * range)
1096 GtsPoint * p1, * p2, * p;
1097 GtsVector p1p2;
1098 gdouble l, t, dt;
1099 guint i, n;
1101 g_return_if_fail (tree != NULL);
1102 g_return_if_fail (s != NULL);
1103 g_return_if_fail (distance != NULL);
1104 g_return_if_fail (delta > 0.);
1105 g_return_if_fail (range != NULL);
1107 p1 = GTS_POINT (s->v1);
1108 p2 = GTS_POINT (s->v2);
1110 gts_vector_init (p1p2, p1, p2);
1111 gts_range_init (range);
1112 p = GTS_POINT (gts_object_new (GTS_OBJECT_CLASS (gts_point_class())));
1114 l = sqrt (gts_vector_scalar (p1p2, p1p2));
1115 n = (guint) (l/delta + 1);
1116 dt = 1.0/(gdouble) n;
1117 t = 0.0;
1118 for (i = 0; i <= n; i++, t += dt) {
1119 p->x = p1->x + t*p1p2[0];
1120 p->y = p1->y + t*p1p2[1];
1121 p->z = p1->z + t*p1p2[2];
1123 gts_range_add_value (range,
1124 gts_bb_tree_point_distance (tree, p, distance, NULL));
1127 gts_object_destroy (GTS_OBJECT (p));
1128 gts_range_update (range);
1131 static void surface_distance_foreach_triangle (GtsTriangle * t,
1132 gpointer * data)
1134 gdouble * delta = data[1];
1135 GtsRange * range = data[2];
1136 gdouble * total_area = data[3], area;
1137 GtsRange range_triangle;
1139 gts_bb_tree_triangle_distance (data[0], t, data[4], *delta, &range_triangle);
1141 if (range_triangle.min < range->min)
1142 range->min = range_triangle.min;
1143 if (range_triangle.max > range->max)
1144 range->max = range_triangle.max;
1145 range->n += range_triangle.n;
1147 area = gts_triangle_area (t);
1148 *total_area += area;
1149 range->sum += area*range_triangle.mean;
1150 range->sum2 += area*range_triangle.mean*range_triangle.mean;
1154 * gts_bb_tree_surface_distance:
1155 * @tree: a bounding box tree.
1156 * @s: a #GtsSurface.
1157 * @distance: a #GtsBBoxDistFunc.
1158 * @delta: a sampling increment defined as the percentage of the diagonal
1159 * of the root bounding box of @tree.
1160 * @range: a #GtsRange to be filled with the results.
1162 * Calls gts_bb_tree_triangle_distance() for each face of @s. The
1163 * fields of @range are filled with the minimum, maximum and average
1164 * distance. The average distance is defined as the sum of the average
1165 * distances for each triangle weighthed by their area and divided by
1166 * the total area of the surface. The standard deviation is defined
1167 * accordingly. The @n field of @range is filled with the number of
1168 * sampled points used.
1170 void gts_bb_tree_surface_distance (GNode * tree,
1171 GtsSurface * s,
1172 GtsBBoxDistFunc distance,
1173 gdouble delta,
1174 GtsRange * range)
1176 gpointer data[5];
1177 gdouble total_area = 0.;
1179 g_return_if_fail (tree != NULL);
1180 g_return_if_fail (s != NULL);
1181 g_return_if_fail (delta > 0. && delta < 1.);
1182 g_return_if_fail (range != NULL);
1184 gts_range_init (range);
1185 delta *= sqrt (gts_bbox_diagonal2 (tree->data));
1186 data[0] = tree;
1187 data[1] = &delta;
1188 data[2] = range;
1189 data[3] = &total_area;
1190 data[4] = distance;
1192 gts_surface_foreach_face (s,
1193 (GtsFunc) surface_distance_foreach_triangle,
1194 data);
1196 if (total_area > 0.) {
1197 if (range->sum2 - range->sum*range->sum/total_area >= 0.)
1198 range->stddev = sqrt ((range->sum2 - range->sum*range->sum/total_area)
1199 /total_area);
1200 else
1201 range->stddev = 0.;
1202 range->mean = range->sum/total_area;
1204 else
1205 range->min = range->max = range->mean = range->stddev = 0.;
1208 static void surface_distance_foreach_boundary (GtsEdge * e,
1209 gpointer * data)
1211 gdouble * delta = data[1];
1212 GtsRange * range = data[2];
1213 gdouble * total_length = data[3], length;
1214 GtsRange range_edge;
1216 if (gts_edge_is_boundary (e, NULL)) {
1217 GtsSegment * s = GTS_SEGMENT (e);
1219 gts_bb_tree_segment_distance (data[0], s, data[4], *delta, &range_edge);
1221 if (range_edge.min < range->min)
1222 range->min = range_edge.min;
1223 if (range_edge.max > range->max)
1224 range->max = range_edge.max;
1225 range->n += range_edge.n;
1227 length = gts_point_distance (GTS_POINT (s->v1), GTS_POINT (s->v2));
1228 *total_length += length;
1229 range->sum += length*range_edge.mean;
1230 range->sum2 += length*range_edge.mean*range_edge.mean;
1235 * gts_bb_tree_surface_boundary_distance:
1236 * @tree: a bounding box tree.
1237 * @s: a #GtsSurface.
1238 * @distance: a #GtsBBoxDistFunc.
1239 * @delta: a sampling increment defined as the percentage of the diagonal
1240 * of the root bounding box of @tree.
1241 * @range: a #GtsRange to be filled with the results.
1243 * Calls gts_bb_tree_segment_distance() for each edge boundary of @s.
1244 * The fields of @range are filled with the minimum, maximum and
1245 * average distance. The average distance is defined as the sum of the
1246 * average distances for each boundary edge weighthed by their length
1247 * and divided by the total length of the boundaries. The standard
1248 * deviation is defined accordingly. The @n field of @range is filled
1249 * with the number of sampled points used.
1251 void gts_bb_tree_surface_boundary_distance (GNode * tree,
1252 GtsSurface * s,
1253 gdouble (*distance) (GtsPoint *,
1254 gpointer),
1255 gdouble delta,
1256 GtsRange * range)
1258 gpointer data[5];
1259 gdouble total_length = 0.;
1261 g_return_if_fail (tree != NULL);
1262 g_return_if_fail (s != NULL);
1263 g_return_if_fail (delta > 0. && delta < 1.);
1264 g_return_if_fail (range != NULL);
1266 gts_range_init (range);
1267 delta *= sqrt (gts_bbox_diagonal2 (tree->data));
1268 data[0] = tree;
1269 data[1] = &delta;
1270 data[2] = range;
1271 data[3] = &total_length;
1272 data[4] = distance;
1274 gts_surface_foreach_edge (s,
1275 (GtsFunc) surface_distance_foreach_boundary,
1276 data);
1278 if (total_length > 0.) {
1279 if (range->sum2 - range->sum*range->sum/total_length >= 0.)
1280 range->stddev = sqrt ((range->sum2 -
1281 range->sum*range->sum/total_length)
1282 /total_length);
1283 else
1284 range->stddev = 0.;
1285 range->mean = range->sum/total_length;
1287 else
1288 range->min = range->max = range->mean = range->stddev = 0.;