123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /*!
- * \file find.c
- *
- * \brief Vector library - Find nearest vector feature.
- *
- * Higher 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 or Mike
- * Higgins.
- * \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
- */
- #include <grass/config.h>
- #include <math.h>
- #include <grass/gis.h>
- #include <grass/vector.h>
- #ifndef HUGE_VAL
- #define HUGE_VAL 9999999999999.0
- #endif
- /*!
- * \brief Find the nearest node.
- *
- * \param Map vector map
- * \param ux,uy,uz point coordinates
- * \param maxdist max distance from the line
- * \param with_z 3D (WITH_Z, WITHOUT_Z)
- *
- * \return number of nearest node
- * \return 0 if not found
- */
- int
- Vect_find_node(struct Map_info *Map,
- double ux, double uy, double uz, double maxdist, int with_z)
- {
- int i, nnodes, node;
- struct bound_box box;
- struct ilist *NList;
- double x, y, z;
- double cur_dist, dist;
- G_debug(3, "Vect_find_node() for %f %f %f maxdist = %f", ux, uy, uz,
- maxdist);
- NList = Vect_new_list();
- /* Select all nodes in box */
- box.N = uy + maxdist;
- box.S = uy - maxdist;
- box.E = ux + maxdist;
- box.W = ux - maxdist;
- if (with_z) {
- box.T = uz + maxdist;
- box.B = uz - maxdist;
- }
- else {
- box.T = HUGE_VAL;
- box.B = -HUGE_VAL;
- }
- nnodes = Vect_select_nodes_by_box(Map, &box, NList);
- G_debug(3, " %d nodes in box", nnodes);
- if (nnodes == 0)
- return 0;
- /* find nearest */
- cur_dist = PORT_DOUBLE_MAX;
- node = 0;
- for (i = 0; i < nnodes; i++) {
- Vect_get_node_coor(Map, NList->value[i], &x, &y, &z);
- dist = Vect_points_distance(ux, uy, uz, x, y, z, with_z);
- if (dist < cur_dist) {
- cur_dist = dist;
- node = i;
- }
- }
- G_debug(3, " nearest node %d in distance %f", NList->value[node],
- cur_dist);
- /* Check if in max distance */
- if (cur_dist <= maxdist)
- return (NList->value[node]);
- else
- return 0;
- }
- /*!
- * \brief Find the nearest line.
- *
- * \param map vector map
- * \param ux,uy,uz points coordinates
- * \param type feature type (GV_LINE, GV_POINT, GV_BOUNDARY or GV_CENTROID)
- * if only want to search certain types of lines or -1 if search all lines
- * \param maxdist max distance from the line
- * \param with_z 3D (WITH_Z, WITHOUT_Z)
- * \param exclude if > 0 number of line which should be excluded from selection.
- * May be useful if we need line nearest to other one.
- *
- * \return number of nearest line
- * \return 0 if not found
- *
- */
- int
- Vect_find_line(struct Map_info *map,
- double ux, double uy, double uz,
- int type, double maxdist, int with_z, int exclude)
- {
- int line;
- struct ilist *exclude_list;
- exclude_list = Vect_new_list();
- Vect_list_append(exclude_list, exclude);
- line = Vect_find_line_list(map, ux, uy, uz,
- type, maxdist, with_z, exclude_list, NULL);
- Vect_destroy_list(exclude_list);
- return line;
- }
- /*!
- * \brief Find the nearest line(s).
- *
- * \param map vector map
- * \param ux,uy,uz points coordinates
- * \param type feature type (GV_LINE, GV_POINT, GV_BOUNDARY or GV_CENTROID)
- * if only want to search certain types of lines or -1 if search all lines
- * \param maxdist max distance from the line
- * \param with_z 3D (WITH_Z, WITHOUT_Z)
- * \param exclude list of lines which should be excluded from selection
- * \param found list of found lines (or NULL)
- *
- * \return number of nearest line
- * \return 0 if not found
- */
- int
- Vect_find_line_list(struct Map_info *map,
- double ux, double uy, double uz,
- int type, double maxdist, int with_z,
- const struct ilist *exclude, struct ilist *found)
- {
- int choice;
- double new_dist;
- double cur_dist;
- int gotone;
- int i, line;
- static struct line_pnts *Points;
- static int first_time = 1;
- const struct Plus_head *Plus;
- struct bound_box box;
- struct ilist *List;
- G_debug(3, "Vect_find_line_list() for %f %f %f type = %d maxdist = %f",
- ux, uy, uz, type, maxdist);
- if (first_time) {
- Points = Vect_new_line_struct();
- first_time = 0;
- }
- Plus = &(map->plus);
- gotone = 0;
- choice = 0;
- cur_dist = HUGE_VAL;
- box.N = uy + maxdist;
- box.S = uy - maxdist;
- box.E = ux + maxdist;
- box.W = ux - maxdist;
- if (with_z) {
- box.T = uz + maxdist;
- box.B = uz - maxdist;
- }
- else {
- box.T = PORT_DOUBLE_MAX;
- box.B = -PORT_DOUBLE_MAX;
- }
- List = Vect_new_list();
- if (found)
- Vect_reset_list(found);
- Vect_select_lines_by_box(map, &box, type, List);
- for (i = 0; i < List->n_values; i++) {
- line = List->value[i];
- if (Vect_val_in_list(exclude, line)) {
- G_debug(3, " line = %d exclude", line);
- continue;
- }
- /* No more needed */
- /*
- Line = Plus->Line[line];
- if ( Line == NULL ) continue;
- if ( !(type & Line->type) ) continue;
- */
- Vect_read_line(map, Points, NULL, line);
- Vect_line_distance(Points, ux, uy, uz, with_z, NULL, NULL, NULL,
- &new_dist, NULL, NULL);
- G_debug(3, " line = %d distance = %f", line, new_dist);
- if (found && new_dist <= maxdist) {
- Vect_list_append(found, line);
- }
- if ((++gotone == 1) || (new_dist <= cur_dist)) {
- if (new_dist == cur_dist) {
- /* TODO */
- /* choice = dig_center_check (map->Line, choice, a, ux, uy); */
- continue;
- }
- choice = line;
- cur_dist = new_dist;
- }
- }
- G_debug(3, "min distance found = %f", cur_dist);
- if (cur_dist > maxdist)
- choice = 0;
- Vect_destroy_list(List);
- return (choice);
- }
- /*!
- * \brief Find the nearest area
- *
- * \param Map vector map
- * \param x,y point coordinates
- *
- * \return area number
- * \return 0 if not found
- */
- int Vect_find_area(struct Map_info *Map, double x, double y)
- {
- int i, ret, area;
- static int first = 1;
- struct bound_box box;
- static struct ilist *List;
- G_debug(3, "Vect_find_area() x = %f y = %f", x, y);
- if (first) {
- List = Vect_new_list();
- first = 0;
- }
- /* select areas by box */
- box.E = x;
- box.W = x;
- box.N = y;
- box.S = y;
- box.T = PORT_DOUBLE_MAX;
- box.B = -PORT_DOUBLE_MAX;
- Vect_select_areas_by_box(Map, &box, List);
- G_debug(3, " %d areas selected by box", List->n_values);
- for (i = 0; i < List->n_values; i++) {
- area = List->value[i];
- ret = Vect_point_in_area(Map, area, x, y);
- G_debug(3, " area = %d Vect_point_in_area() = %d", area, ret);
- if (ret >= 1)
- return (area);
- }
- return 0;
- }
- /*!
- * \brief Find the nearest island
- *
- * \param Map vector map
- * \param x,y points coordinates
- *
- * \return island number,
- * \return 0 if not found
- */
- int Vect_find_island(struct Map_info *Map, double x, double y)
- {
- int i, ret, island, current, current_size, size;
- static int first = 1;
- struct bound_box box;
- static struct ilist *List;
- static struct line_pnts *Points;
- G_debug(3, "Vect_find_island() x = %f y = %f", x, y);
- if (first) {
- List = Vect_new_list();
- Points = Vect_new_line_struct();
- first = 0;
- }
- /* select islands by box */
- box.E = x;
- box.W = x;
- box.N = y;
- box.S = y;
- box.T = PORT_DOUBLE_MAX;
- box.B = -PORT_DOUBLE_MAX;
- Vect_select_isles_by_box(Map, &box, List);
- G_debug(3, " %d islands selected by box", List->n_values);
- current_size = -1;
- current = 0;
- for (i = 0; i < List->n_values; i++) {
- island = List->value[i];
- ret = Vect_point_in_island(x, y, Map, island);
- if (ret >= 1) { /* inside */
- if (current > 0) { /* not first */
- if (current_size == -1) { /* second */
- G_begin_polygon_area_calculations();
- Vect_get_isle_points(Map, current, Points);
- current_size =
- G_area_of_polygon(Points->x, Points->y,
- Points->n_points);
- }
- Vect_get_isle_points(Map, island, Points);
- size =
- G_area_of_polygon(Points->x, Points->y, Points->n_points);
- if (size < current_size) {
- current = island;
- current_size = size;
- }
- }
- else { /* first */
- current = island;
- }
- }
- }
- return current;
- }
|