pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* GTS - Library for the manipulation of triangulated surfaces 00002 * Copyright (C) 1999 Stéphane Popinet 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Library General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Library General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this library; if not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 * Boston, MA 02111-1307, USA. 00018 */ 00019 00020 #include <stdlib.h> 00021 #include "gts.h" 00022 00023 00024 static int compare_x (const void * p1, const void * p2) { 00025 GtsPoint 00026 * pp1 = *((gpointer *) p1), 00027 * pp2 = *((gpointer *) p2); 00028 if (pp1->x > pp2->x) 00029 return 1; 00030 return -1; 00031 } 00032 00033 static int compare_y (const void * p1, const void * p2) { 00034 GtsPoint 00035 * pp1 = *((gpointer *) p1), 00036 * pp2 = *((gpointer *) p2); 00037 if (pp1->y > pp2->y) 00038 return 1; 00039 return -1; 00040 } 00041 00042 static int compare_z (const void * p1, const void * p2) { 00043 GtsPoint 00044 * pp1 = *((gpointer *) p1), 00045 * pp2 = *((gpointer *) p2); 00046 if (pp1->z > pp2->z) 00047 return 1; 00048 return -1; 00049 } 00050 00061 GNode * gts_kdtree_new (GPtrArray * points, 00062 int (*compare) (const void *, const void *)) 00063 { 00064 guint middle; 00065 GPtrArray array; 00066 GNode * node; 00067 GtsPoint * point; 00068 00069 g_return_val_if_fail (points != NULL, NULL); 00070 g_return_val_if_fail (points->len > 0, NULL); 00071 00072 /* sort the points */ 00073 if (compare == compare_x) compare = compare_y; 00074 else if (compare == compare_y) compare = compare_z; 00075 else compare = compare_x; 00076 qsort (points->pdata, points->len, sizeof (gpointer), compare); 00077 00078 middle = (points->len - 1)/2; 00079 point = points->pdata[middle]; 00080 node = g_node_new (point); 00081 00082 if (points->len > 1) { 00083 array.len = middle; 00084 if (array.len > 0) { 00085 array.pdata = points->pdata; 00086 g_node_prepend (node, gts_kdtree_new (&array, compare)); 00087 } 00088 else 00089 g_node_prepend (node, g_node_new (NULL)); 00090 00091 array.len = points->len - middle - 1; 00092 if (array.len > 0) { 00093 array.pdata = &(points->pdata[middle + 1]); 00094 g_node_prepend (node, gts_kdtree_new (&array, compare)); 00095 } 00096 else 00097 g_node_prepend (node, g_node_new (NULL)); 00098 } 00099 00100 return node; 00101 } 00102 00111 GSList * gts_kdtree_range (GNode * tree_3d, 00112 GtsBBox * bbox, 00113 int (*compare) (const void *, const void *)) 00114 { 00115 GSList * list = NULL; 00116 GtsPoint * p; 00117 gdouble left, right, v; 00118 GNode * node; 00119 00120 g_return_val_if_fail (tree_3d != NULL, NULL); 00121 g_return_val_if_fail (bbox != NULL, NULL); 00122 00123 p = tree_3d->data; 00124 if (p == NULL) 00125 return NULL; 00126 00127 if (gts_bbox_point_is_inside (bbox, p)) 00128 list = g_slist_prepend (list, p); 00129 00130 if (compare == compare_x) { 00131 left = bbox->y1; right = bbox->y2; v = p->y; 00132 compare = compare_y; 00133 } 00134 else if (compare == compare_y) { 00135 left = bbox->z1; right = bbox->z2; v = p->z; 00136 compare = compare_z; 00137 } 00138 else { 00139 left = bbox->x1; right = bbox->x2; v = p->x; 00140 compare = compare_x; 00141 } 00142 00143 if ((node = tree_3d->children)) { 00144 if (right >= v) 00145 list = g_slist_concat (list, gts_kdtree_range (node, bbox, compare)); 00146 node = node->next; 00147 if (left <= v) 00148 list = g_slist_concat (list, gts_kdtree_range (node, bbox, compare)); 00149 } 00150 return list; 00151 } 00152