source: grass/trunk/vector/v.edit/select.c

Last change on this file was 65297, checked in by marisn, 9 years ago

Rename _n macro to n_ to avoid clashes with other libs (as sugested in dev ML)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 14.4 KB
Line 
1
2/****************************************************************
3 *
4 * MODULE: v.edit
5 *
6 * PURPOSE: Editing vector map.
7 *
8 * AUTHOR(S): GRASS Development Team
9 * Wolf Bergenheim, Jachym Cepicky, Martin Landa
10 *
11 * COPYRIGHT: (C) 2006-2008 by the GRASS Development Team
12 *
13 * This program is free software under the
14 * GNU General Public License (>=v2).
15 * Read the file COPYING that comes with GRASS
16 * for details.
17 *
18 * TODO: 3D support
19 ****************************************************************/
20
21#include <grass/dbmi.h>
22#include "global.h"
23
24static char first_selection = 1;
25static int merge_lists(struct ilist *, struct ilist *);
26static int merge_lists2(struct ilist *, struct boxlist *);
27
28/**
29 \brief Select vector features
30
31 \param[in] Map vector map
32 \param[in] action_mode tool
33 \param[in] params GRASS parameters
34 \param[in] List list of selected features
35
36 \return list of newly selected features
37*/
38struct ilist *select_lines(struct Map_info *Map, enum mode action_mode,
39 struct GParams *params, double *thresh,
40 struct ilist *List)
41{
42 int layer, type;
43
44 layer = Vect_get_field_number(Map, params->fld->answer);
45 type = Vect_option_to_types(params->type);
46
47 /* select by id's */
48 if (params->id->answer != NULL) {
49 sel_by_id(Map, type, params->id->answer, List);
50 }
51
52 /* select by category (ignore tools catdel and catadd) */
53 if ((action_mode != MODE_CATADD && action_mode != MODE_CATDEL) &&
54 params->cat->answer != NULL) {
55 sel_by_cat(Map, NULL, layer, type, params->cat->answer, List);
56 }
57
58 /* select by coordinates (+threshold) */
59 if (params->coord->answer != NULL) {
60 int i;
61 double east, north;
62 struct line_pnts *coords;
63
64 coords = Vect_new_line_struct();
65 i = 0;
66 while (params->coord->answers[i]) {
67 east = atof(params->coord->answers[i]);
68 north = atof(params->coord->answers[i + 1]);
69 Vect_append_point(coords, east, north, 0.0);
70 i += 2;
71 }
72
73 G_verbose_message(_("Threshold value for coordinates is %.2f"),
74 thresh[THRESH_COORDS]);
75 sel_by_coordinates(Map, type, coords, thresh[THRESH_COORDS], List);
76
77 Vect_destroy_line_struct(coords);
78 }
79
80 /* select by bbox */
81 if (params->bbox->answer != NULL) {
82 struct line_pnts *bbox;
83 double x1, y1, x2, y2;
84
85 bbox = Vect_new_line_struct();
86
87 x1 = atof(params->bbox->answers[0]);
88 y1 = atof(params->bbox->answers[1]);
89 x2 = atof(params->bbox->answers[2]);
90 y2 = atof(params->bbox->answers[3]);
91
92 Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
93 Vect_append_point(bbox, x2, y1, PORT_DOUBLE_MAX);
94 Vect_append_point(bbox, x2, y2, -PORT_DOUBLE_MAX);
95 Vect_append_point(bbox, x1, y2, PORT_DOUBLE_MAX);
96 Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
97
98 /* sel_by_bbox not used */
99 /*
100 sel_by_bbox(Map,
101 type, x1, y1, x2, y2,
102 List);
103 */
104 sel_by_polygon(Map, type, bbox, List);
105
106 Vect_destroy_line_struct(bbox);
107 }
108
109 /* select by polygon */
110 if (params->poly->answer != NULL) {
111 int i;
112 struct line_pnts *Polygon;
113
114 Polygon = Vect_new_line_struct();
115
116 for (i = 0; params->poly->answers[i]; i += 2) {
117 Vect_append_point(Polygon,
118 atof(params->poly->answers[i]),
119 atof(params->poly->answers[i + 1]), 0.0);
120 }
121
122 /* if first and last point of polygon does not match */
123 if (atof(params->poly->answers[i - 1]) !=
124 atof(params->poly->answers[0])) {
125 Vect_append_point(Polygon, atof(params->poly->answers[0]),
126 atof(params->poly->answers[1]), 0.0);
127 }
128
129 sel_by_polygon(Map, type, Polygon, List);
130
131 Vect_destroy_line_struct(Polygon);
132 }
133
134 /* select by where statement */
135 if (params->where->answer != NULL) {
136 sel_by_where(Map, layer, type, params->where->answer, List);
137 }
138
139 /* selecy by query */
140 if (params->query->answer != NULL) {
141 int query_type;
142 struct ilist *List_tmp;
143
144 if (first_selection) {
145 List_tmp = List;
146 first_selection = 0;
147 }
148 else {
149 List_tmp = Vect_new_list();
150 }
151
152 query_type = QUERY_UNKNOWN;
153 if (strcmp(params->query->answer, "length") == 0) {
154 query_type = QUERY_LENGTH;
155 }
156 else if (strcmp(params->query->answer, "dangle") == 0) {
157 query_type = QUERY_DANGLE;
158 }
159
160 G_verbose_message(_("Threshold value for querying is %.2f"),
161 thresh[THRESH_QUERY]);
162 Vedit_select_by_query(Map, type, layer, thresh[THRESH_QUERY],
163 query_type, List_tmp);
164
165 /* merge lists (only duplicate items) */
166 if (List_tmp != List) {
167 merge_lists(List, List_tmp);
168 Vect_destroy_list(List_tmp);
169 }
170 }
171
172 if (params->reverse->answer) {
173 reverse_selection(Map, type, &List);
174 }
175
176 G_message(n_("%d of %d feature selected from vector map <%s>",
177 "%d of %d features selected from vector map <%s>",
178 Vect_get_num_lines(Map)
179 ),
180 List->n_values,
181 Vect_get_num_lines(Map), Vect_get_full_name(Map));
182
183 return List;
184}
185
186/**
187 \brief Print selected vector features
188
189 \param[in] List list of selected features
190
191 \return number of selected features
192 \return -1 on error
193*/
194int print_selected(struct ilist *List)
195{
196 int i;
197
198 /* print the result */
199 for (i = 0; i < List->n_values; i++) {
200 fprintf(stdout, "%d%s",
201 List->value[i], i < List->n_values - 1 ? "," : "");
202 }
203 if (List->n_values > 0) {
204 fprintf(stdout, "\n");
205 }
206 fflush(stdout);
207
208 return List->n_values;
209}
210
211/**
212 \brief Select features by category
213
214 \param[in] Map vector map
215 \param[in] cl_orig original list of categories (previously selected)
216 \param[in] layer layer number
217 \param[in] type feature type
218 \param[in] cat category string
219 \param[in,out] List list of selected features
220
221 \return number of selected lines
222*/
223int sel_by_cat(struct Map_info *Map, struct cat_list *cl_orig,
224 int layer, int type, char *cats, struct ilist *List)
225{
226 struct ilist *List_tmp, *List_tmp1;
227 struct cat_list *cl;
228
229 int i, cat;
230
231 if (first_selection || cl_orig) {
232 List_tmp = List;
233 first_selection = 0;
234 }
235 else {
236 List_tmp = Vect_new_list();
237 }
238
239 List_tmp1 = Vect_new_list();
240
241 if (cl_orig == NULL) {
242 cl = Vect_new_cat_list();
243
244 Vect_str_to_cat_list(cats, cl);
245 }
246 else {
247 cl = cl_orig;
248 }
249
250 for (i = 0; i < cl->n_ranges; i++) {
251 for (cat = cl->min[i]; cat <= cl->max[i]; cat++) {
252 Vect_cidx_find_all(Map, layer, type, cat, List_tmp1);
253 Vect_list_append_list(List_tmp, List_tmp1);
254 }
255 }
256
257 G_debug(1, " %d lines selected (by category)", List_tmp->n_values);
258
259 /* merge lists (only duplicate items) */
260 if (List_tmp != List) {
261 merge_lists(List, List_tmp);
262 Vect_destroy_list(List_tmp);
263 }
264
265 Vect_destroy_list(List_tmp1);
266
267 return List->n_values;
268}
269
270/**
271 \brief Select features by coordinates
272
273 \param[in] Map vector map
274 \param[in] type feature type
275 \param[in] coords coordinates GRASS parameters
276 \param[in] thresh threshold value for searching
277 \param[in,out] List list of selected features
278
279 \return number of selected lines
280*/
281int sel_by_coordinates(struct Map_info *Map,
282 int type, struct line_pnts *coords, double thresh,
283 struct ilist *List)
284{
285 int i;
286 double east, north, maxdist;
287
288 struct ilist *List_tmp, *List_in_box;
289 struct line_pnts *box;
290
291 if (first_selection) {
292 List_tmp = List;
293 first_selection = 0;
294 }
295 else {
296 List_tmp = Vect_new_list();
297 }
298
299 box = Vect_new_line_struct();
300 List_in_box = Vect_new_list();
301
302 if (thresh < 0)
303 maxdist = max_distance(thresh);
304 else
305 maxdist = thresh;
306
307 for (i = 0; i < coords->n_points; i++) {
308 east = coords->x[i];
309 north = coords->y[i];
310
311 coord2bbox(east, north, maxdist, box);
312
313 Vect_select_lines_by_polygon(Map, box, 0, NULL, type, List_in_box);
314
315 if (List_in_box->n_values > 0)
316 Vect_list_append_list(List_tmp, List_in_box);
317 }
318
319 G_debug(1, " %d lines selected (by coordinates)", List_tmp->n_values);
320
321 /* merge lists (only duplicate items) */
322 if (List_tmp != List) {
323 merge_lists(List, List_tmp);
324 Vect_destroy_list(List_tmp);
325 }
326
327 Vect_destroy_line_struct(box);
328 Vect_destroy_list(List_in_box);
329
330 return List->n_values;
331}
332
333/**
334 \brief Select features by bbox
335
336 \param[in] Map vector map
337 \param[in] type feature type
338 \param[in] bbox_opt bounding boxes
339 \param[in,out] List list of selected features
340
341 \return number of selected lines
342*/
343int sel_by_bbox(struct Map_info *Map,
344 int type, double x1, double y1, double x2, double y2,
345 struct ilist *List)
346{
347 struct bound_box bbox;
348
349 struct boxlist *List_tmp;
350
351 List_tmp = Vect_new_boxlist(0);
352
353 /* bounding box */
354 bbox.N = y1 < y2 ? y2 : y1;
355 bbox.S = y1 < y2 ? y1 : y2;
356 bbox.W = x1 < x2 ? x1 : x2;
357 bbox.E = x1 < x2 ? x2 : x1;
358 bbox.T = PORT_DOUBLE_MAX;
359 bbox.B = -PORT_DOUBLE_MAX;
360
361 Vect_select_lines_by_box(Map, &bbox, type, List_tmp);
362
363 G_debug(1, " %d lines selected (by bbox)", List_tmp->n_values);
364
365 /* merge lists (only duplicate items) */
366 merge_lists2(List, List_tmp);
367 Vect_destroy_boxlist(List_tmp);
368
369 return List->n_values;
370}
371
372/**
373 \brief Select features by polygon
374
375 \param[in] Map vector map
376 \param[in] type feature type
377 \param[in] poly polygon coordinates
378 \param[in,out] List list of selected features
379
380 \return number of selected lines
381*/
382int sel_by_polygon(struct Map_info *Map,
383 int type, struct line_pnts *Polygon, struct ilist *List)
384{
385 struct ilist *List_tmp;
386
387 if (first_selection) {
388 List_tmp = List;
389 first_selection = 0;
390 }
391 else {
392 List_tmp = Vect_new_list();
393 }
394
395 /* no isles */
396 Vect_select_lines_by_polygon(Map, Polygon, 0, NULL, type, List_tmp);
397
398 G_debug(1, " %d lines selected (by polygon)", List_tmp->n_values);
399
400 /* merge lists (only duplicate items) */
401 if (List_tmp != List) {
402 merge_lists(List, List_tmp);
403 Vect_destroy_list(List_tmp);
404 }
405
406 return List->n_values;
407}
408
409/**
410 \brief Select features by id
411
412 \param[in] Map vector map
413 \param[in] type feature type
414 \param[in] ids ids list
415 \param[in,out] List list of selected features
416
417 \return number of selected lines
418*/
419int sel_by_id(struct Map_info *Map, int type, char *ids, struct ilist *List)
420{
421 int i;
422 int num, id;
423 struct cat_list *il; /* NOTE: this is not cat list, but list of id's */
424 struct ilist *List_tmp;
425
426 if (first_selection) {
427 List_tmp = List;
428 first_selection = 0;
429 }
430 else {
431 List_tmp = Vect_new_list();
432 }
433
434 il = Vect_new_cat_list();
435 Vect_str_to_cat_list(ids, il);
436
437 num = Vect_get_num_lines(Map);
438
439 for (i = 0; i < il->n_ranges; i++) {
440 for (id = 1; id <= num; id++) {
441 if (!(Vect_read_line(Map, NULL, NULL, id) & type)) {
442 continue;
443 }
444 if (id >= il->min[i] && id <= il->max[i]) {
445 Vect_list_append(List_tmp, id);
446 }
447 }
448 }
449
450 G_debug(1, " %d lines selected (by id)", List_tmp->n_values);
451
452 /* merge lists (only duplicate items) */
453 if (List_tmp != List) {
454 merge_lists(List, List_tmp);
455 Vect_destroy_list(List_tmp);
456 }
457
458 Vect_destroy_cat_list(il);
459
460 return List->n_values;
461}
462
463/**
464 \brief Select features according to SQL where statement
465
466 \param[in] Map vector map
467 \param[in] layer layer number
468 \param[in] type feature type
469 \param[in] where 'where' statement
470 \param[in,out] List list of selected features
471
472 \return number of selected lines
473*/
474int sel_by_where(struct Map_info *Map,
475 int layer, int type, char *where, struct ilist *List)
476{
477 struct cat_list *cat_list;
478 struct ilist *List_tmp;
479 struct field_info *Fi;
480 dbDriver *driver;
481 dbHandle handle;
482
483 int *cats, ncats;
484
485 if (first_selection) {
486 List_tmp = List;
487 first_selection = 0;
488 }
489 else {
490 List_tmp = Vect_new_list();
491 }
492
493 cat_list = Vect_new_cat_list();
494
495 if (layer < 1) {
496 G_fatal_error(_("Layer must be > 0 for 'where'"));
497 }
498
499 Fi = Vect_get_field(Map, layer);
500
501 if (!Fi) {
502 G_fatal_error(_("Database connection not defined for layer %d"),
503 layer);
504 }
505
506 driver = db_start_driver(Fi->driver);
507
508 if (!driver)
509 G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
510
511 db_init_handle(&handle);
512
513 db_set_handle(&handle, Fi->database, NULL);
514
515 if (db_open_database(driver, &handle) != DB_OK)
516 G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
517 Fi->database, Fi->driver);
518 db_set_error_handler_driver(driver);
519
520 ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
521
522 db_close_database(driver);
523 db_shutdown_driver(driver);
524
525 Vect_array_to_cat_list(cats, ncats, cat_list);
526
527 /* free array of cats */
528 if (ncats >= 0)
529 G_free(cats);
530
531 sel_by_cat(Map, cat_list, layer, type, NULL, List_tmp);
532
533 G_debug(1, " %d lines selected (by where)", List_tmp->n_values);
534
535 /* merge lists (only duplicate items) */
536 if (List_tmp != List) {
537 merge_lists(List, List_tmp);
538 Vect_destroy_list(List_tmp);
539 }
540
541 Vect_destroy_cat_list(cat_list);
542
543 return List->n_values;
544}
545
546/**
547 \brief merge two lists, i.e. store only duplicate items
548
549 \param[in] alist,blist list to be merged
550
551 \return result number of items
552*/
553static int merge_lists(struct ilist *alist, struct ilist *blist)
554{
555 int i;
556
557 struct ilist *list_del;
558
559 list_del = Vect_new_list();
560
561 for (i = 0; i < alist->n_values; i++) {
562 if (!Vect_val_in_list(blist, alist->value[i]))
563 Vect_list_append(list_del, alist->value[i]);
564 }
565
566 Vect_list_delete_list(alist, list_del);
567
568 Vect_destroy_list(list_del);
569
570 return alist->n_values;
571}
572
573/**
574 \brief merge two lists, i.e. store only duplicate items
575
576 \param[in] alist,blist list to be merged
577
578 \return result number of items
579*/
580static int merge_lists2(struct ilist *alist, struct boxlist *blist)
581{
582 int i;
583
584 struct ilist *list_del;
585
586 list_del = Vect_new_list();
587
588 for (i = 0; i < alist->n_values; i++) {
589 if (!Vect_val_in_boxlist(blist, alist->value[i]))
590 Vect_list_append(list_del, alist->value[i]);
591 }
592
593 Vect_list_delete_list(alist, list_del);
594
595 Vect_destroy_list(list_del);
596
597 return alist->n_values;
598}
599
600/**
601 \brief Reverse list selection
602
603 \param[in] Map vector map
604 \param[in] type feature type
605 \param[in,out] reversed list
606
607 \return 1
608*/
609int reverse_selection(struct Map_info *Map, int type, struct ilist **List)
610{
611
612 struct ilist *list_reverse;
613 int line, nlines, ltype;
614
615 list_reverse = Vect_new_list();
616
617 nlines = Vect_get_num_lines(Map);
618
619 for (line = 1; line <= nlines; line++) {
620 ltype = Vect_read_line(Map, NULL, NULL, line);
621
622 if (!(ltype & type))
623 continue;
624
625 if (!Vect_val_in_list(*List, line))
626 Vect_list_append(list_reverse, line);
627 }
628
629 Vect_destroy_list(*List);
630 *List = list_reverse;
631
632 return 1;
633}
Note: See TracBrowser for help on using the repository browser.