123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- /*!
- \file diglib/spindex.c
- \brief Vector library - spatial index (lower level functions)
- Lower level functions for reading/writing/manipulating vectors.
- (C) 2001-2009 by the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- \author Original author CERL, probably Dave Gerdes
- \author Update to GRASS 5.7 Radim Blazek
- \author Update to GRASS 7 Markus Metz
- */
- #include <grass/config.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- /*!
- \brief Initit spatial index (nodes, lines, areas, isles)
- \param Plus pointer to Plus_head structure
- \return 1 OK
- \return 0 on error
- */
- int dig_spidx_init(struct Plus_head *Plus)
- {
- int ndims;
- ndims = Plus->with_z ? 3 : 2;
- G_debug(1, "dig_spidx_init()");
- G_debug(1, "Plus->spidx_separate = %d", Plus->Spidx_new);
- Plus->Node_spidx = RTreeNewIndex(ndims);
- Plus->Line_spidx = RTreeNewIndex(ndims);
- Plus->Area_spidx = RTreeNewIndex(ndims);
- Plus->Isle_spidx = RTreeNewIndex(ndims);
- Plus->Face_spidx = NULL;
- Plus->Volume_spidx = NULL;
- Plus->Hole_spidx = NULL;
- Plus->Node_spidx_offset = 0L;
- Plus->Line_spidx_offset = 0L;
- Plus->Area_spidx_offset = 0L;
- Plus->Isle_spidx_offset = 0L;
- Plus->Face_spidx_offset = 0L;
- Plus->Volume_spidx_offset = 0L;
- Plus->Hole_spidx_offset = 0L;
- return 1;
- }
- /*!
- \brief Free spatial index for nodes
- \param Plus pointer to Plus_head structure
- */
- void dig_spidx_free_nodes(struct Plus_head *Plus)
- {
- int ndims;
- ndims = Plus->with_z ? 3 : 2;
- /* Node spidx */
- RTreeFreeIndex(Plus->Node_spidx);
- Plus->Node_spidx = RTreeNewIndex(ndims);
- }
- /*!
- \brief Free spatial index for lines
- \param Plus pointer to Plus_head structure
- */
- void dig_spidx_free_lines(struct Plus_head *Plus)
- {
- int ndims;
- ndims = Plus->with_z ? 3 : 2;
- /* Line spidx */
- RTreeFreeIndex(Plus->Line_spidx);
- Plus->Line_spidx = RTreeNewIndex(ndims);
- }
- /*!
- \brief Reset spatial index for areas
- \param Plus pointer to Plus_head structure
- */
- void dig_spidx_free_areas(struct Plus_head *Plus)
- {
- int ndims;
- ndims = Plus->with_z ? 3 : 2;
- /* Area spidx */
- RTreeFreeIndex(Plus->Area_spidx);
- Plus->Area_spidx = RTreeNewIndex(ndims);
- }
- /*!
- \brief Reset spatial index for isles
- \param Plus pointer to Plus_head structure
- */
- void dig_spidx_free_isles(struct Plus_head *Plus)
- {
- int ndims;
- ndims = Plus->with_z ? 3 : 2;
- /* Isle spidx */
- RTreeFreeIndex(Plus->Isle_spidx);
- Plus->Isle_spidx = RTreeNewIndex(ndims);
- }
- /*!
- \brief Free spatial index (nodes, lines, areas, isles)
- \param Plus pointer to Plus_head structure
- */
- void dig_spidx_free(struct Plus_head *Plus)
- {
- /* Node spidx */
- RTreeFreeIndex(Plus->Node_spidx);
- /* Line spidx */
- RTreeFreeIndex(Plus->Line_spidx);
- /* Area spidx */
- RTreeFreeIndex(Plus->Area_spidx);
- /* Isle spidx */
- RTreeFreeIndex(Plus->Isle_spidx);
- }
- /*!
- \brief Add new node to spatial index
- \param Plus pointer to Plus_head structure
- \param node node id
- \param x,y,z node coordinates
- \return 1 OK
- \return 0 on error
- */
- int
- dig_spidx_add_node(struct Plus_head *Plus, int node,
- double x, double y, double z)
- {
- struct Rect rect;
- G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
- y, z);
- rect.boundary[0] = x;
- rect.boundary[1] = y;
- rect.boundary[2] = z;
- rect.boundary[3] = x;
- rect.boundary[4] = y;
- rect.boundary[5] = z;
- RTreeInsertRect(&rect, node, Plus->Node_spidx);
- return 1;
- }
- /*!
- \brief Add new line to spatial index
- \param Plus pointer to Plus_head structure
- \param line line id
- \param box bounding box
- \return 0
- */
- int dig_spidx_add_line(struct Plus_head *Plus, int line, struct bound_box * box)
- {
- struct Rect rect;
- G_debug(3, "dig_spidx_add_line(): line = %d", line);
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- RTreeInsertRect(&rect, line, Plus->Line_spidx);
- return 0;
- }
- /*!
- \brief Add new area to spatial index
- \param Plus pointer to Plus_head structure
- \param area area id
- \param box bounding box
- \return 0
- */
- int dig_spidx_add_area(struct Plus_head *Plus, int area, struct bound_box * box)
- {
- struct Rect rect;
- G_debug(3, "dig_spidx_add_area(): area = %d", area);
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- RTreeInsertRect(&rect, area, Plus->Area_spidx);
- return 0;
- }
- /*!
- \brief Add new island to spatial index
- \param Plus pointer to Plus_head structure
- \param isle isle id
- \param box bounding box
- \return 0
- */
- int dig_spidx_add_isle(struct Plus_head *Plus, int isle, struct bound_box * box)
- {
- struct Rect rect;
- G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- RTreeInsertRect(&rect, isle, Plus->Isle_spidx);
- return 0;
- }
- /*!
- \brief Delete node from spatial index
- G_fatal_error() called on error.
- \param Plus pointer to Plus_head structure
- \param node node id
- \return 0
- */
- int dig_spidx_del_node(struct Plus_head *Plus, int node)
- {
- int ret;
- struct P_node *Node;
- struct Rect rect;
- G_debug(3, "dig_spidx_del_node(): node = %d", node);
- Node = Plus->Node[node];
- 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;
- ret = RTreeDeleteRect(&rect, node, Plus->Node_spidx);
- if (ret)
- G_fatal_error(_("Unable to delete node %d from spatial index"), node);
- return 0;
- }
- /*!
- \brief Delete line from spatial index
- G_fatal_error() called on error.
- \param Plus pointer to Plus_head structure
- \param line line id
- \return 0
- */
- int dig_spidx_del_line(struct Plus_head *Plus, int line)
- {
- struct P_line *Line;
- struct Rect rect;
- int ret;
- G_debug(3, "dig_spidx_del_line(): line = %d", line);
- Line = Plus->Line[line];
- G_debug(3, " box(x1,y1,z1,x2,y2,z2): %f %f %f %f %f %f", Line->W,
- Line->S, Line->B, Line->E, Line->N, Line->T);
- rect.boundary[0] = Line->W;
- rect.boundary[1] = Line->S;
- rect.boundary[2] = Line->B;
- rect.boundary[3] = Line->E;
- rect.boundary[4] = Line->N;
- rect.boundary[5] = Line->T;
- ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
- G_debug(3, " ret = %d", ret);
- if (ret)
- G_fatal_error(_("Unable to delete line %d from spatial index"), line);
- return 0;
- }
- /*!
- \brief Delete area from spatial index
- G_fatal_error() called on error.
- \param Plus pointer to Plus_head structure
- \param area area id
- \return 0
- */
- int dig_spidx_del_area(struct Plus_head *Plus, int area)
- {
- int ret;
- struct P_area *Area;
- struct Rect rect;
- G_debug(3, "dig_spidx_del_area(): area = %d", area);
- Area = Plus->Area[area];
- if (Area == NULL) {
- G_fatal_error(_("Attempt to delete sidx for dead area"));
- }
- rect.boundary[0] = Area->W;
- rect.boundary[1] = Area->S;
- rect.boundary[2] = Area->B;
- rect.boundary[3] = Area->E;
- rect.boundary[4] = Area->N;
- rect.boundary[5] = Area->T;
- ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
- if (ret)
- G_fatal_error(_("Unable to delete area %d from spatial index"), area);
- return 0;
- }
- /*!
- \brief Delete isle from spatial index
- G_fatal_error() called on error.
- \param Plus pointer to Plus_head structure
- \param isle isle id
- \return 0
- */
- int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
- {
- int ret;
- struct P_isle *Isle;
- struct Rect rect;
- G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
- Isle = Plus->Isle[isle];
- rect.boundary[0] = Isle->W;
- rect.boundary[1] = Isle->S;
- rect.boundary[2] = Isle->B;
- rect.boundary[3] = Isle->E;
- rect.boundary[4] = Isle->N;
- rect.boundary[5] = Isle->T;
- ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
- if (ret)
- G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
- return 0;
- }
- /* This function is called by RTreeSearch() to add selected node/line/area/isle to thelist */
- static int _add_item(int id, struct ilist *list)
- {
- dig_list_add(list, id);
- return 1;
- }
- /*!
- \brief Select nodes by bbox
- \param Plus pointer to Plus_head structure
- \param box bounding box
- \param list list of selected lines
- \return number of selected nodes
- \return -1 on error
- */
- int
- dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
- struct ilist *list)
- {
- struct Rect rect;
- G_debug(3, "dig_select_nodes()");
- list->n_values = 0;
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- if (Plus->Spidx_new)
- RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
- else
- rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
- return (list->n_values);
- }
- /* This function is called by RTreeSearch() for nodes to add selected node to list */
- static int _add_node(int id, int *node)
- {
- *node = id;
- return 0;
- }
- /*!
- \brief Find one node by coordinates
- \param Plus pointer to Plus_head structure
- \param x,y,z coordinates
- \return number of node
- \return 0 not found
- */
- int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
- {
- struct Rect rect;
- struct ilist list;
- int node;
- G_debug(3, "dig_find_node()");
- dig_init_list(&list);
- rect.boundary[0] = x;
- rect.boundary[1] = y;
- rect.boundary[2] = z;
- rect.boundary[3] = x;
- rect.boundary[4] = y;
- rect.boundary[5] = z;
- node = 0;
- if (Plus->Spidx_new)
- RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
- else
- rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
- return node;
- }
- /*!
- \brief Select lines by box
- \param Plus pointer to Plus_head structure
- \param box bounding box
- \param list list of selected lines
- \return number of selected lines
- */
- int
- dig_select_lines(struct Plus_head *Plus, const struct bound_box * box,
- struct ilist *list)
- {
- struct Rect rect;
- G_debug(3, "dig_select_lines()");
- list->n_values = 0;
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- if (Plus->Spidx_new)
- RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item, list);
- else
- rtree_search(Plus->Line_spidx, &rect, (void *)_add_item, list, Plus);
- return (list->n_values);
- }
- /*!
- \brief Select areas by box
- \param Plus pointer to Plus_head structure
- \param box bounding box
- \param list list of selected lines
- \return number of selected areas
- */
- int
- dig_select_areas(struct Plus_head *Plus, const struct bound_box * box,
- struct ilist *list)
- {
- struct Rect rect;
- G_debug(3, "dig_select_areas()");
- list->n_values = 0;
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- if (Plus->Spidx_new)
- RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item, list);
- else
- rtree_search(Plus->Area_spidx, &rect, (void *)_add_item, list, Plus);
- return (list->n_values);
- }
- /*!
- \brief Select isles by box
- \param Plus pointer to Plus_head structure
- \param box bounding box
- \param list list of selected lines
- \return number of selected isles
- */
- int
- dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
- struct ilist *list)
- {
- struct Rect rect;
- G_debug(3, "dig_select_isles()");
- list->n_values = 0;
- rect.boundary[0] = box->W;
- rect.boundary[1] = box->S;
- rect.boundary[2] = box->B;
- rect.boundary[3] = box->E;
- rect.boundary[4] = box->N;
- rect.boundary[5] = box->T;
- if (Plus->Spidx_new)
- RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item, list);
- else
- rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item, list, Plus);
- return (list->n_values);
- }
|