GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
vector/vedit/select.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/vedit/select.c
3 
4  \brief Vedit library - select primitives by query
5 
6  (C) 2007-2008 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Martin Landa <landa.martin gmail.com>
12 */
13 
14 #include <math.h>
15 #include <grass/glocale.h>
16 #include <grass/vedit.h>
17 
18 static int select_by_query(struct Map_info *, int, int, double,
19  int, struct line_pnts *, struct line_cats *);
20 
21 static int merge_lists(struct ilist *alist, struct ilist *blist);
22 
23 /*!
24  \brief Select primitives by query (based on geometry properties)
25 
26  Currently supported:
27  - QUERY_LENGTH, select all lines longer than threshold (or shorter if threshold is < 0)
28  - QUERY_DANGLE, select all dangles longer than threshold (or shorter if threshold is < 0)
29 
30  Perform global query if <i>List</i> is empty otherwise query only
31  selected vector objects.
32 
33  \param Map pointer to Map_info
34  \param type feature type
35  \param layer layer number
36  \param thresh threshold value (< 0 for 'shorter', > 0 for 'longer')
37  \param query query (length, dangle, ...)
38  \param[in,out] List list of selected features
39 
40  \return number of selected primitives
41 */
43  int type, int layer, double thresh, int query,
44  struct ilist *List)
45 {
46  int num, line, i;
47  double thresh_tmp;
48  struct line_pnts *Points;
49  struct line_cats *Cats;
50  struct ilist *List_query;
51 
52  Points = Vect_new_line_struct();
53  Cats = Vect_new_cats_struct();
54 
55  if (List->n_values == 0) {
56  List_query = List;
57  }
58  else {
59  List_query = Vect_new_list();
60  }
61 
62  switch (query) {
63  case QUERY_LENGTH:{
64  if (List->n_values == 0) {
65  /* query all vector objects in vector map */
66  num = Vect_get_num_lines(Map);
67  for (line = 1; line <= num; line++) {
68  if (select_by_query(Map, line, type, thresh,
69  query, Points, Cats))
70  Vect_list_append(List_query, line);
71  }
72  }
73  else {
74  for (i = 0; i < List->n_values; i++) {
75  line = List->value[i];
76  if (select_by_query(Map, line, type, thresh,
77  query, Points, Cats)) {
78  Vect_list_append(List_query, line);
79  }
80  }
81  }
82  break;
83  }
84  case QUERY_DANGLE:{
85  struct ilist *List_dangle;
86 
87  List_dangle = Vect_new_list();
88  thresh_tmp = fabs(thresh);
89 
90  /* select dangles shorter than 'thresh_tmp' */
91  Vect_select_dangles(Map, type, thresh_tmp, List_dangle);
92 
93  if (thresh <= 0.0) { /* shorter than */
94  for (i = 0; i < List_dangle->n_values; i++) {
95  Vect_list_append(List_query, List_dangle->value[i]);
96  }
97  }
98  else { /* longer than */
99  for (i = 1; i <= Vect_get_num_lines(Map); i++) {
100  if (!Vect_val_in_list(List_dangle, i))
101  Vect_list_append(List_query, i);
102  }
103  }
104 
105  Vect_destroy_list(List_dangle);
106  break;
107  }
108  default:
109  break;
110  }
111 
112  if (List != List_query) {
113  merge_lists(List, List_query);
114  Vect_destroy_list(List_query);
115  }
116 
117  G_debug(3, "Vedit_select_by_query(): %d lines selected (by query %d)",
118  List->n_values, query);
119 
120  Vect_destroy_line_struct(Points);
122 
123  return List->n_values;
124 }
125 
126 /*!
127  \brief Query selected primitive
128 
129  \return 1 line test positive
130  \return 0 line test negative
131  \return -1 on error (line is dead)
132 */
133 int select_by_query(struct Map_info *Map, int line, int type, double thresh,
134  int query, struct line_pnts *Points,
135  struct line_cats *Cats)
136 {
137  int ltype;
138  double length;
139  int i, cat_curr;
140  int node1, node2, node; /* nodes */
141  int nnode1, nnode2; /* number of line in node */
142  double nx, ny, nz; /* node coordinates */
143  struct ilist *exclude, *found; /* line id of nearest lines */
144  struct line_cats *Cats_curr;
145 
146  if (!Vect_line_alive(Map, line))
147  return -1;
148 
149  ltype = Vect_read_line(Map, Points, Cats, line);
150 
151  if (!(ltype & type))
152  return -1;
153 
154  if (query == QUERY_LENGTH) {
155  length = Vect_line_length(Points);
156  if (thresh <= 0.0) { /* shorter then */
157  if (length <= fabs(thresh))
158  return 1;
159  }
160  else { /* longer then */
161  if (length > thresh)
162  return 1;
163  }
164  }
165  else if (query == QUERY_DANGLE) {
166  /*
167  this code is currently replaced by Vect_select_dangle()
168  not used by v.edit
169  */
170  int layer, cat;
171 
172  layer = 1;
173  Vect_cat_get(Cats, layer, &cat); /* get first category from layer */
174  if (!(type & GV_LINES))
175  return -1;
176  /* check if line is dangle */
177 
178  Vect_get_line_nodes(Map, line, &node1, &node2);
179 
180  node = -1;
181  nnode1 = Vect_get_node_n_lines(Map, node1);
182  nnode2 = Vect_get_node_n_lines(Map, node2);
183 
184  if ((nnode1 == 4 && nnode2 == 1) || (nnode1 == 1 && nnode2 == 4)) {
185  if (nnode1 == 4)
186  node = node1;
187  else
188  node = node2;
189  }
190 
191  /* no dangle ? */
192  if (node == -1)
193  return -1;
194 
195  length = Vect_line_length(Points);
196  if (thresh <= 0.0) { /* shorter then */
197  if (length > fabs(thresh))
198  return -1;
199  }
200  else { /* longer then */
201  if (length <= thresh)
202  return -1;
203  }
204 
205  /* at least one of the lines need to have same category number */
206  exclude = Vect_new_list();
207  found = Vect_new_list();
208 
209  Vect_get_node_coor(Map, node, &nx, &ny, &nz);
210 
211  Vect_list_append(exclude, line);
212  Vect_find_line_list(Map, nx, ny, nz,
213  GV_LINES, 0.0, WITHOUT_Z, exclude, found);
214 
215  Cats_curr = Vect_new_cats_struct();
216 
217  for (i = 0; i < found->n_values; i++) {
218  Vect_read_line(Map, NULL, Cats_curr, found->value[i]);
219  if (Vect_cat_get(Cats_curr, layer, &cat_curr) > -1) {
220  if (cat == cat_curr)
221  return 1;
222  }
223  }
224 
225  Vect_destroy_cats_struct(Cats_curr);
226  Vect_destroy_list(exclude);
227  Vect_destroy_list(found);
228  }
229  else {
230  /* this shouldn't happen */
231  G_fatal_error("Vedit_select_by_query(): %s", _("Unknown query tool"));
232  }
233 
234  return 0;
235 }
236 
237 /*!
238  \brief Merge two lists, i.e. store only duplicate items
239 
240  \param[in,out] alist list to be merged
241  \param blist list used for merging
242 
243  \return result number of items
244 */
245 int merge_lists(struct ilist *alist, struct ilist *blist)
246 {
247  int i;
248 
249  struct ilist *list_del;
250 
251  list_del = Vect_new_list();
252 
253  for (i = 0; i < alist->n_values; i++) {
254  if (!Vect_val_in_list(blist, alist->value[i]))
255  Vect_list_append(list_del, alist->value[i]);
256  }
257 
258  Vect_list_delete_list(alist, list_del);
259 
260  Vect_destroy_list(list_del);
261 
262  return alist->n_values;
263 }
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
plus_t Vect_get_num_lines(const struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:74
int Vect_val_in_list(const struct ilist *, int)
Find a given item in the list.
int n_values
Number of values in the list.
Definition: gis.h:709
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition: line.c:576
#define NULL
Definition: ccmath.h:32
int Vect_get_node_n_lines(const struct Map_info *, int)
Get number of lines for node.
Definition: level_two.c:384
Feature category info.
Definition: dig_structs.h:1702
int Vect_get_node_coor(const struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition: level_two.c:278
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
void Vect_select_dangles(struct Map_info *, int, double, struct ilist *)
Select dangles from vector map.
Definition: dangles.c:101
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int * cat
Array of categories.
Definition: dig_structs.h:1711
int Vedit_select_by_query(struct Map_info *Map, int type, int layer, double thresh, int query, struct ilist *List)
Select primitives by query (based on geometry properties)
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:170
int Vect_get_line_nodes(const struct Map_info *, int, int *, int *)
Get line nodes.
Definition: level_two.c:307
Vector map info.
Definition: dig_structs.h:1259
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
int Vect_line_alive(const struct Map_info *, int)
Check if feature is alive or dead (topological level required)
#define QUERY_DANGLE
Definition: vedit.h:13
#define _(str)
Definition: glocale.h:10
List of integers.
Definition: gis.h:700
int * value
Array of values.
Definition: gis.h:705
#define GV_LINES
Definition: dig_defines.h:192
int Vect_find_line_list(struct Map_info *, double, double, double, int, double, int, const struct ilist *, struct ilist *)
Find the nearest line(s).
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition: line.c:77
int Vect_read_line(const struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_list_delete_list(struct ilist *, const struct ilist *)
Delete list from existing list.
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
#define QUERY_LENGTH
Definition: vedit.h:12