[GRASS-SVN] r52542 - in grass/trunk: include/vect lib/vector/Vlib lib/vector/diglib

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Aug 5 12:42:38 PDT 2012


Author: mmetz
Date: 2012-08-05 12:42:38 -0700 (Sun, 05 Aug 2012)
New Revision: 52542

Modified:
   grass/trunk/include/vect/dig_externs.h
   grass/trunk/lib/vector/Vlib/box.c
   grass/trunk/lib/vector/diglib/spindex.c
Log:
vector libs: optimize bbox search

Modified: grass/trunk/include/vect/dig_externs.h
===================================================================
--- grass/trunk/include/vect/dig_externs.h	2012-08-05 19:33:54 UTC (rev 52541)
+++ grass/trunk/include/vect/dig_externs.h	2012-08-05 19:42:38 UTC (rev 52542)
@@ -207,9 +207,9 @@
 int dig_select_areas(struct Plus_head *, const struct bound_box *, struct boxlist *);
 int dig_select_isles(struct Plus_head *, const struct bound_box *, struct boxlist *);
 int dig_find_node(struct Plus_head *, double, double, double);
-int dig_find_line_box(struct Plus_head *, struct boxlist *);
-int dig_find_area_box(struct Plus_head *, struct boxlist *);
-int dig_find_isle_box(struct Plus_head *, struct boxlist *);
+int dig_find_line_box(struct Plus_head *, int, struct bound_box *);
+int dig_find_area_box(struct Plus_head *, int, struct bound_box *);
+int dig_find_isle_box(struct Plus_head *, int, struct bound_box *);
 
 /* spindex_rw.c */
 int dig_Rd_spidx_head(struct gvfile  *, struct Plus_head *);

Modified: grass/trunk/lib/vector/Vlib/box.c
===================================================================
--- grass/trunk/lib/vector/Vlib/box.c	2012-08-05 19:33:54 UTC (rev 52541)
+++ grass/trunk/lib/vector/Vlib/box.c	2012-08-05 19:42:38 UTC (rev 52542)
@@ -28,15 +28,12 @@
    \return 1 point is in box
    \return 0 point is not in box
  */
-int Vect_point_in_box(double x, double y, double z, const struct bound_box * Box)
+int Vect_point_in_box(double x, double y, double z, const struct bound_box *Box)
 {
 
-    if (x >= Box->W && x <= Box->E &&
-	y >= Box->S && y <= Box->N && z >= Box->B && z <= Box->T) {
-	return 1;
-    }
-
-    return 0;
+    return (x >= Box->W && x <= Box->E &&
+	    y >= Box->S && y <= Box->N && 
+	    z >= Box->B && z <= Box->T);
 }
 
 /*!
@@ -48,7 +45,7 @@
    \return 1 boxes overlap
    \return 0 boxes do not overlap
  */
-int Vect_box_overlap(const struct bound_box * A, const struct bound_box * B)
+int Vect_box_overlap(const struct bound_box *A, const struct bound_box *B)
 {
 
     if (A->E < B->W || A->W > B->E ||
@@ -67,7 +64,7 @@
 
    \return 1
  */
-int Vect_box_copy(struct bound_box * A, const struct bound_box * B)
+int Vect_box_copy(struct bound_box *A, const struct bound_box *B)
 {
 
     A->N = B->N;
@@ -88,7 +85,7 @@
 
    \return 1
  */
-int Vect_box_extend(struct bound_box * A, const struct bound_box * B)
+int Vect_box_extend(struct bound_box *A, const struct bound_box *B)
 {
 
     if (B->N > A->N)
@@ -133,7 +130,7 @@
  */
 
 int
-Vect_box_clip(double *x, double *y, double *c_x, double *c_y, const struct bound_box * Box)
+Vect_box_clip(double *x, double *y, double *c_x, double *c_y, const struct bound_box *Box)
 {
     int mod;
 
@@ -202,19 +199,18 @@
    \return 1 on success
    \return 0 line is dead
  */
-int Vect_get_line_box(const struct Map_info *Map, int line, struct bound_box * Box)
+int Vect_get_line_box(const struct Map_info *Map, int line, struct bound_box *Box)
 {
     struct Plus_head *Plus;
     struct P_line *Line;
     int type;
     static struct line_pnts *Points = NULL;
-    static struct boxlist *list = NULL;
 
     Plus = (struct Plus_head *)&(Map->plus);
     Line = Plus->Line[line];
 
     if (Line == NULL) {		/* dead */
-	G_zero(Box, sizeof(struct bound_box));
+	Box->N = Box->S = Box->E = Box->W = Box->T = Box->B = 0. / 0.;
 	return 0;
     }
 	
@@ -222,44 +218,10 @@
 
     /* GV_LINES: retrieve box from spatial index */
     if (type & GV_LINES) {
-	int node = 0;
-	struct bound_box bbox;
-
-	if (type == GV_LINE) {
-	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
-
-	    node = topo->N1;
-	}
-	else if (type == GV_BOUNDARY) {
-	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
-
-	    node = topo->N1;
-	}
 	
-	if (list == NULL) {
-	    list = Vect_new_boxlist(1);
-	}
-	Vect_reset_boxlist(list);
-	
-	bbox.N = Plus->Node[node]->y;
-	bbox.S = Plus->Node[node]->y;
-	bbox.E = Plus->Node[node]->x;
-	bbox.W = Plus->Node[node]->x;
-	bbox.T = Plus->Node[node]->z;
-	bbox.B = Plus->Node[node]->z;
-
-	dig_boxlist_add(list, line, bbox);
-	
-	if (dig_find_line_box(Plus, list) == 0)
+	if (dig_find_line_box(Plus, line, Box) == 0)
 	    G_fatal_error(_("Unable to find bbox for feature %d"), line);
 
-	Box->N = list->box[0].N;
-	Box->S = list->box[0].S;
-	Box->E = list->box[0].E;
-	Box->W = list->box[0].W;
-	Box->T = list->box[0].T;
-	Box->B = list->box[0].B;
-
 	if (!Vect_is_3d(Map)) {
 	    Box->T =  PORT_DOUBLE_MAX;
 	    Box->B = -PORT_DOUBLE_MAX;
@@ -294,52 +256,27 @@
    \return 1 on success
    \return 0 area is dead
  */
-int Vect_get_area_box(const struct Map_info *Map, int area, struct bound_box * Box)
+int Vect_get_area_box(const struct Map_info *Map, int area, struct bound_box *Box)
 {
     struct Plus_head *Plus;
     struct P_area *Area;
-    struct P_line *Line;
-    struct P_node *Node;
-    static struct boxlist *list = NULL;
-    struct bound_box bbox;
-    struct P_topo_b *topo;
 
     Plus = (struct Plus_head *)&(Map->plus);
     Area = Plus->Area[area];
 
     if (Area == NULL) {		/* dead */
-        G_zero(Box, sizeof(struct bound_box));
+	Box->N = Box->S = Box->E = Box->W = Box->T = Box->B = 0. / 0.;
 	return 0;
     }
 
-    Line = Plus->Line[abs(Area->lines[0])];
-    topo = (struct P_topo_b *)Line->topo;
-    Node = Plus->Node[topo->N1];
+    if (dig_find_area_box(Plus, area, Box) == 0)
+	G_fatal_error(_("Unable to get bounding box for area %d"), area);
 
-    if (list == NULL) {
-	list = Vect_new_boxlist(TRUE);
+    if (!Vect_is_3d(Map)) {
+	Box->T =  PORT_DOUBLE_MAX;
+	Box->B = -PORT_DOUBLE_MAX;
     }
-    Vect_reset_boxlist(list);
-    
-    bbox.N = Node->y;
-    bbox.S = Node->y;
-    bbox.E = Node->x;
-    bbox.W = Node->x;
-    bbox.T = Node->z;
-    bbox.B = Node->z;
 
-    dig_boxlist_add(list, area, bbox);
-    
-    if (dig_find_area_box(Plus, list) == 0)
-	G_fatal_error(_("Unable to get bounding box for area %d"), area);
-
-    Box->N = list->box[0].N;
-    Box->S = list->box[0].S;
-    Box->E = list->box[0].E;
-    Box->W = list->box[0].W;
-    Box->T = list->box[0].T;
-    Box->B = list->box[0].B;
-
     return 1;
 }
 
@@ -351,59 +288,29 @@
    \param[out] Box bounding box
 
    \return 1 on success
-   \return 0 isle is dead
+   \return 0 isle is dead / bounding box not found
  */
-int Vect_get_isle_box(const struct Map_info *Map, int isle, struct bound_box * Box)
+int Vect_get_isle_box(const struct Map_info *Map, int isle, struct bound_box *Box)
 {
     struct Plus_head *Plus;
     struct P_isle *Isle;
-    struct P_line *Line;
-    struct P_node *Node;
-    static struct boxlist *list = NULL;
-    struct bound_box bbox;
-    struct P_topo_b *topo;
 
     Plus = (struct Plus_head *)&(Map->plus);
     Isle = Plus->Isle[isle];
 
     if (Isle == NULL) {		/* dead */
-	Box->N = 0;
-	Box->S = 0;
-	Box->E = 0;
-	Box->W = 0;
-	Box->T = 0;
-	Box->B = 0;
+	Box->N = Box->S = Box->E = Box->W = Box->T = Box->B = 0. / 0.;
 	return 0;
     }
 
-    Line = Plus->Line[abs(Isle->lines[0])];
-    topo = (struct P_topo_b *)Line->topo;
-    Node = Plus->Node[topo->N1];
+    if (dig_find_isle_box(Plus, isle, Box) == 0)
+	G_fatal_error(_("Could not find isle box"));
 
-    if (list == NULL) {
-	list = Vect_new_boxlist(1);
+    if (!Vect_is_3d(Map)) {
+	Box->T =  PORT_DOUBLE_MAX;
+	Box->B = -PORT_DOUBLE_MAX;
     }
-    Vect_reset_boxlist(list);
-    
-    bbox.N = Node->y;
-    bbox.S = Node->y;
-    bbox.E = Node->x;
-    bbox.W = Node->x;
-    bbox.T = Node->z;
-    bbox.B = Node->z;
 
-    dig_boxlist_add(list, isle, bbox);
-    
-    if (dig_find_isle_box(Plus, list) == 0)
-	G_fatal_error(_("Could not find isle box"));
-
-    Box->N = list->box[0].N;
-    Box->S = list->box[0].S;
-    Box->E = list->box[0].E;
-    Box->W = list->box[0].W;
-    Box->T = list->box[0].T;
-    Box->B = list->box[0].B;
-
     return 1;
 }
 
@@ -416,7 +323,7 @@
    \return 1 on success
    \return 0 on error
  */
-int Vect_get_map_box(const struct Map_info *Map, struct bound_box * Box)
+int Vect_get_map_box(const struct Map_info *Map, struct bound_box *Box)
 {
     const struct Plus_head *Plus;
 
@@ -442,7 +349,7 @@
    \return 1 on success
    \return 0 on error
  */
-int Vect_region_box(const struct Cell_head *Window, struct bound_box * Box)
+int Vect_region_box(const struct Cell_head *Window, struct bound_box *Box)
 {
 
     Box->N = Window->north;

Modified: grass/trunk/lib/vector/diglib/spindex.c
===================================================================
--- grass/trunk/lib/vector/diglib/spindex.c	2012-08-05 19:33:54 UTC (rev 52541)
+++ grass/trunk/lib/vector/diglib/spindex.c	2012-08-05 19:42:38 UTC (rev 52542)
@@ -287,7 +287,8 @@
 
    \return 0
  */
-int dig_spidx_add_line(struct Plus_head *Plus, int line, const struct bound_box * box)
+int dig_spidx_add_line(struct Plus_head *Plus, int line,
+                       const struct bound_box *box)
 {
     static struct RTree_Rect rect;
     static int rect_init = 0;
@@ -320,7 +321,8 @@
 
    \return 0
  */
-int dig_spidx_add_area(struct Plus_head *Plus, int area, const struct bound_box * box)
+int dig_spidx_add_area(struct Plus_head *Plus, int area,
+                       const struct bound_box *box)
 {
     static struct RTree_Rect rect;
     static int rect_init = 0;
@@ -354,7 +356,8 @@
    \return 0
  */
 
-int dig_spidx_add_isle(struct Plus_head *Plus, int isle, const struct bound_box * box)
+int dig_spidx_add_isle(struct Plus_head *Plus, int isle,
+                       const struct bound_box *box)
 {
     static struct RTree_Rect rect;
     static int rect_init = 0;
@@ -430,7 +433,8 @@
 
    \return 0
  */
-int dig_spidx_del_line(struct Plus_head *Plus, int line, double x, double y, double z)
+int dig_spidx_del_line(struct Plus_head *Plus, int line,
+                       double x, double y, double z)
 {
     int ret;
     static struct RTree_Rect rect;
@@ -572,7 +576,8 @@
 
 /* This function is called by RTreeSearch() to add 
  * selected node/line/area/isle to the box list */
-static int _add_item_with_box(int id, struct RTree_Rect rect, struct boxlist *list)
+static int _add_item_with_box(int id, struct RTree_Rect rect,
+                              struct boxlist *list)
 {
     struct bound_box box;
     
@@ -587,18 +592,25 @@
     return 1;
 }
 
+struct boxid
+{
+    int id;
+    struct bound_box *box;
+};
+
 /* This function is called by RTreeSearch() to add 
  * selected node/line/area/isle to the box list */
-static int _set_item_box(int id, struct RTree_Rect rect, struct boxlist *list)
+static int _set_item_box(int id, struct RTree_Rect rect,
+                         struct boxid *box_id)
 {
-    if (id == list->id[0]) {
+    if (id == box_id->id) {
 	
-	list->box[0].W = rect.boundary[0];
-	list->box[0].S = rect.boundary[1];
-	list->box[0].B = rect.boundary[2];
-	list->box[0].E = rect.boundary[3];
-	list->box[0].N = rect.boundary[4];
-	list->box[0].T = rect.boundary[5];
+	box_id->box->W = rect.boundary[0];
+	box_id->box->S = rect.boundary[1];
+	box_id->box->B = rect.boundary[2];
+	box_id->box->E = rect.boundary[3];
+	box_id->box->N = rect.boundary[4];
+	box_id->box->T = rect.boundary[5];
 	
 	return 0;
     }
@@ -739,41 +751,71 @@
    \brief Find box for line
 
    \param Plus pointer to Plus_head structure
-   \param[in,out] list line with isle id and search box (in)/line box (out)
+   \param line line id
+   \param[out] box bounding box
 
-   \return number of lines found
+   \return > 0 bounding box for line found
    \return 0 not found
  */
-int dig_find_line_box(struct Plus_head *Plus, struct boxlist *list)
+int dig_find_line_box(struct Plus_head *Plus, int line,
+                      struct bound_box *box)
 {
-    int ret;
+    int ret, type;
+    struct P_line *Line;
+    struct boxid box_id;
     static struct RTree_Rect rect;
     static int rect_init = 0;
 
+    G_debug(3, "dig_find_line_box()");
+
     if (!rect_init) {
 	/* always 6 sides for 3D */
 	rect.boundary = G_malloc(6 * sizeof(RectReal));
 	rect_init = 6;
     }
 
-    G_debug(3, "dig_find_line_box()");
+    Line = Plus->Line[line];
+    type = Line->type;
 
-    if (list->n_values < 1)
-	G_fatal_error(_("No line id given"));
+    /* GV_LINES: retrieve box from spatial index */
+    if (type & GV_LINES) {
+	struct P_node *Node = NULL;
 
-    rect.boundary[0] = list->box[0].W;
-    rect.boundary[1] = list->box[0].S;
-    rect.boundary[2] = list->box[0].B;
-    rect.boundary[3] = list->box[0].E;
-    rect.boundary[4] = list->box[0].N;
-    rect.boundary[5] = list->box[0].T;
+	if (type == GV_LINE) {
+	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
 
-    if (Plus->Spidx_new)
-	ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, list);
-    else
-	ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, list, Plus);
+	    Node = Plus->Node[topo->N1];
+	}
+	else if (type == GV_BOUNDARY) {
+	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
 
-    return (ret);
+	    Node = Plus->Node[topo->N1];
+	}
+
+	rect.boundary[0] = Node->x;
+	rect.boundary[1] = Node->y;
+	rect.boundary[2] = Node->z;
+	rect.boundary[3] = Node->x;
+	rect.boundary[4] = Node->y;
+	rect.boundary[5] = Node->z;
+	
+	box_id.id = line;
+	box_id.box = box;
+
+	if (Plus->Spidx_new)
+	    ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id);
+	else
+	    ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
+
+	return ret;
+    }
+
+    /* do not translate this error because 
+     * 1. this error is not supposed to happen
+     * 2. the maintainer at which this message is directed prefers english */
+    G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for lines and boundaries.");
+
+    return 0;
 }
 
 /*! 
@@ -786,7 +828,7 @@
    \return number of selected areas
  */
 int
-dig_select_areas(struct Plus_head *Plus, const struct bound_box * box,
+dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
 		 struct boxlist *list)
 {
     static struct RTree_Rect rect;
@@ -821,39 +863,51 @@
    \brief Find bounding box for given area
 
    \param Plus pointer to Plus_head structure
-   \param[in,out] list list with area id and search box (in)/area box (out)
+   \param area area id
+   \param[out] box bounding box
 
-   \return number of areas found
+   \return > 0 bounding box for area found
    \return 0 not found
  */
-int dig_find_area_box(struct Plus_head *Plus, struct boxlist *list)
+int dig_find_area_box(struct Plus_head *Plus, int area,
+                      struct bound_box *box)
 {
     int ret;
+    struct boxid box_id;
+    struct P_area *Area;
+    struct P_line *Line;
+    struct P_node *Node;
+    struct P_topo_b *topo;
     static struct RTree_Rect rect;
     static int rect_init = 0;
 
+    G_debug(3, "dig_find_area_box()");
+
     if (!rect_init) {
 	/* always 6 sides for 3D */
 	rect.boundary = G_malloc(6 * sizeof(RectReal));
 	rect_init = 6;
     }
 
-    G_debug(3, "dig_find_area_box()");
+    Area = Plus->Area[area];
+    Line = Plus->Line[abs(Area->lines[0])];
+    topo = (struct P_topo_b *)Line->topo;
+    Node = Plus->Node[topo->N1];
 
-    if (list->n_values < 1)
-	G_fatal_error(_("No area id given"));
+    rect.boundary[0] = Node->x;
+    rect.boundary[1] = Node->y;
+    rect.boundary[2] = Node->z;
+    rect.boundary[3] = Node->x;
+    rect.boundary[4] = Node->y;
+    rect.boundary[5] = Node->z;
+    
+    box_id.id = area;
+    box_id.box = box;
 
-    rect.boundary[0] = list->box[0].W;
-    rect.boundary[1] = list->box[0].S;
-    rect.boundary[2] = list->box[0].B;
-    rect.boundary[3] = list->box[0].E;
-    rect.boundary[4] = list->box[0].N;
-    rect.boundary[5] = list->box[0].T;
-
     if (Plus->Spidx_new)
-	ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, list);
+	ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id);
     else
-	ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, list, Plus);
+	ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
 
     return ret;
 }
@@ -903,39 +957,51 @@
    \brief Find box for isle
 
    \param Plus pointer to Plus_head structure
-   \param[in,out] list list with isle id and search box (in)/isle box (out)
+   \param isle isle id
+   \param[out] box bounding box
 
-   \return number of isles found
+   \return > 0 bounding box for isle found
    \return 0 not found
  */
-int dig_find_isle_box(struct Plus_head *Plus, struct boxlist *list)
+int dig_find_isle_box(struct Plus_head *Plus, int isle,
+                      struct bound_box *box)
 {
     int ret;
+    struct boxid box_id;
+    struct P_isle *Isle;
+    struct P_line *Line;
+    struct P_node *Node;
+    struct P_topo_b *topo;
     static struct RTree_Rect rect;
     static int rect_init = 0;
 
+    G_debug(3, "dig_find_isle_box()");
+
     if (!rect_init) {
 	/* always 6 sides for 3D */
 	rect.boundary = G_malloc(6 * sizeof(RectReal));
 	rect_init = 6;
     }
 
-    G_debug(3, "dig_find_isle_box()");
+    Isle = Plus->Isle[isle];
+    Line = Plus->Line[abs(Isle->lines[0])];
+    topo = (struct P_topo_b *)Line->topo;
+    Node = Plus->Node[topo->N1];
 
-    if (list->n_values < 1)
-	G_fatal_error(_("No isle id given"));
+    rect.boundary[0] = Node->x;
+    rect.boundary[1] = Node->y;
+    rect.boundary[2] = Node->z;
+    rect.boundary[3] = Node->x;
+    rect.boundary[4] = Node->y;
+    rect.boundary[5] = Node->z;
+    
+    box_id.id = isle;
+    box_id.box = box;
 
-    rect.boundary[0] = list->box[0].W;
-    rect.boundary[1] = list->box[0].S;
-    rect.boundary[2] = list->box[0].B;
-    rect.boundary[3] = list->box[0].E;
-    rect.boundary[4] = list->box[0].N;
-    rect.boundary[5] = list->box[0].T;
-
     if (Plus->Spidx_new)
-	ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, list);
+	ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id);
     else
-	ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, list, Plus);
+	ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
 
-    return (ret);
+    return ret;
 }



More information about the grass-commit mailing list