GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-f4d8c62acd
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, int,
19  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
28  threshold is < 0)
29  - QUERY_DANGLE, select all dangles longer than threshold (or shorter if
30  threshold is < 0)
31 
32  Perform global query if <i>List</i> is empty otherwise query only
33  selected vector objects.
34 
35  \param Map pointer to Map_info
36  \param type feature type
37  \param layer layer number (unused)
38  \param thresh threshold value (< 0 for 'shorter', > 0 for 'longer')
39  \param query query (length, dangle, ...)
40  \param[in,out] List list of selected features
41 
42  \return number of selected primitives
43  */
44 int Vedit_select_by_query(struct Map_info *Map, int type, int layer UNUSED,
45  double thresh, int query, struct ilist *List)
46 {
47  int num, line, i;
48  double thresh_tmp;
49  struct line_pnts *Points;
50  struct line_cats *Cats;
51  struct ilist *List_query;
52 
53  Points = Vect_new_line_struct();
54  Cats = Vect_new_cats_struct();
55 
56  if (List->n_values == 0) {
57  List_query = List;
58  }
59  else {
60  List_query = Vect_new_list();
61  }
62 
63  switch (query) {
64  case QUERY_LENGTH: {
65  if (List->n_values == 0) {
66  /* query all vector objects in vector map */
67  num = Vect_get_num_lines(Map);
68  for (line = 1; line <= num; line++) {
69  if (select_by_query(Map, line, type, thresh, query, Points,
70  Cats))
71  Vect_list_append(List_query, line);
72  }
73  }
74  else {
75  for (i = 0; i < List->n_values; i++) {
76  line = List->value[i];
77  if (select_by_query(Map, line, type, thresh, query, Points,
78  Cats)) {
79  Vect_list_append(List_query, line);
80  }
81  }
82  }
83  break;
84  }
85  case QUERY_DANGLE: {
86  struct ilist *List_dangle;
87 
88  List_dangle = Vect_new_list();
89  thresh_tmp = fabs(thresh);
90 
91  /* select dangles shorter than 'thresh_tmp' */
92  Vect_select_dangles(Map, type, thresh_tmp, List_dangle);
93 
94  if (thresh <= 0.0) { /* shorter than */
95  for (i = 0; i < List_dangle->n_values; i++) {
96  Vect_list_append(List_query, List_dangle->value[i]);
97  }
98  }
99  else { /* longer than */
100  for (i = 1; i <= Vect_get_num_lines(Map); i++) {
101  if (!Vect_val_in_list(List_dangle, i))
102  Vect_list_append(List_query, i);
103  }
104  }
105 
106  Vect_destroy_list(List_dangle);
107  break;
108  }
109  default:
110  break;
111  }
112 
113  if (List != List_query) {
114  merge_lists(List, List_query);
115  Vect_destroy_list(List_query);
116  }
117 
118  G_debug(3, "Vedit_select_by_query(): %d lines selected (by query %d)",
119  List->n_values, query);
120 
121  Vect_destroy_line_struct(Points);
123 
124  return List->n_values;
125 }
126 
127 /*!
128  \brief Query selected primitive
129 
130  \return 1 line test positive
131  \return 0 line test negative
132  \return -1 on error (line is dead)
133  */
134 int select_by_query(struct Map_info *Map, int line, int type, double thresh,
135  int query, struct line_pnts *Points, 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, GV_LINES, 0.0, WITHOUT_Z, exclude,
213  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 }
#define NULL
Definition: ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
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_get_line_nodes(struct Map_info *, int, int *, int *)
Get line nodes.
Definition: level_two.c:303
int Vect_get_node_coor(struct Map_info *, int, double *, double *, double *)
Get node coordinates.
Definition: level_two.c:274
plus_t Vect_get_num_lines(struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:75
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition: line.c:575
void Vect_select_dangles(struct Map_info *, int, double, struct ilist *)
Select dangles from vector map.
Definition: dangles.c:98
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
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_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_list_delete_list(struct ilist *, const struct ilist *)
Delete list from existing list.
int Vect_line_alive(struct Map_info *, int)
Check if feature is alive or dead (topological level required)
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
int Vect_val_in_list(const struct ilist *, int)
Find a given item in the list.
int Vect_get_node_n_lines(struct Map_info *, int)
Get number of lines for node.
Definition: level_two.c:380
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
#define GV_LINES
Definition: dig_defines.h:193
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:171
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:47
#define _(str)
Definition: glocale.h:10
Vector map info.
Definition: dig_structs.h:1243
List of integers.
Definition: gis.h:706
int n_values
Number of values in the list.
Definition: gis.h:714
int * value
Array of values.
Definition: gis.h:710
Feature category info.
Definition: dig_structs.h:1677
int * cat
Array of categories.
Definition: dig_structs.h:1685
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
int Vedit_select_by_query(struct Map_info *Map, int type, int layer UNUSED, double thresh, int query, struct ilist *List)
Select primitives by query (based on geometry properties)
#define QUERY_LENGTH
Definition: vedit.h:12
#define QUERY_DANGLE
Definition: vedit.h:13