pcb 4.1.1
An interactive printed circuit board layout editor.

kdtree.c

Go to the documentation of this file.
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