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.
24 static int compare_x (const void * p1
, const void * p2
) {
26 * pp1
= *((gpointer
*) p1
),
27 * pp2
= *((gpointer
*) p2
);
33 static int compare_y (const void * p1
, const void * p2
) {
35 * pp1
= *((gpointer
*) p1
),
36 * pp2
= *((gpointer
*) p2
);
42 static int compare_z (const void * p1
, const void * p2
) {
44 * pp1
= *((gpointer
*) p1
),
45 * pp2
= *((gpointer
*) p2
);
53 * @points: an array of #GtsPoint.
54 * @compare: always %NULL.
56 * Note that the order of the points in array @points is modified by this
59 * Returns: a new 3D tree for @points.
61 GNode
* gts_kdtree_new (GPtrArray
* points
,
62 int (*compare
) (const void *, const void *))
69 g_return_val_if_fail (points
!= NULL
, NULL
);
70 g_return_val_if_fail (points
->len
> 0, NULL
);
73 if (compare
== compare_x
) compare
= compare_y
;
74 else if (compare
== compare_y
) compare
= compare_z
;
75 else compare
= compare_x
;
76 qsort (points
->pdata
, points
->len
, sizeof (gpointer
), compare
);
78 middle
= (points
->len
- 1)/2;
79 point
= points
->pdata
[middle
];
80 node
= g_node_new (point
);
82 if (points
->len
> 1) {
85 array
.pdata
= points
->pdata
;
86 g_node_prepend (node
, gts_kdtree_new (&array
, compare
));
89 g_node_prepend (node
, g_node_new (NULL
));
91 array
.len
= points
->len
- middle
- 1;
93 array
.pdata
= &(points
->pdata
[middle
+ 1]);
94 g_node_prepend (node
, gts_kdtree_new (&array
, compare
));
97 g_node_prepend (node
, g_node_new (NULL
));
107 * @compare: always %NULL.
109 * Returns: a list of #GtsPoint belonging to @tree which are inside @bbox.
111 GSList
* gts_kdtree_range (GNode
* tree_3d
,
113 int (*compare
) (const void *, const void *))
115 GSList
* list
= NULL
;
117 gdouble left
, right
, v
;
120 g_return_val_if_fail (tree_3d
!= NULL
, NULL
);
121 g_return_val_if_fail (bbox
!= NULL
, NULL
);
127 if (gts_bbox_point_is_inside (bbox
, p
))
128 list
= g_slist_prepend (list
, p
);
130 if (compare
== compare_x
) {
131 left
= bbox
->y1
; right
= bbox
->y2
; v
= p
->y
;
134 else if (compare
== compare_y
) {
135 left
= bbox
->z1
; right
= bbox
->z2
; v
= p
->z
;
139 left
= bbox
->x1
; right
= bbox
->x2
; v
= p
->x
;
143 if ((node
= tree_3d
->children
)) {
145 list
= g_slist_concat (list
, gts_kdtree_range (node
, bbox
, compare
));
148 list
= g_slist_concat (list
, gts_kdtree_range (node
, bbox
, compare
));