select.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /****************************************************************
  2. *
  3. * MODULE: v.edit
  4. *
  5. * PURPOSE: Editing vector map.
  6. *
  7. * AUTHOR(S): GRASS Development Team
  8. * Wolf Bergenheim, Jachym Cepicky, Martin Landa
  9. *
  10. * COPYRIGHT: (C) 2006-2008 by the GRASS Development Team
  11. *
  12. * This program is free software under the
  13. * GNU General Public License (>=v2).
  14. * Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. * TODO: 3D support
  18. ****************************************************************/
  19. #include <grass/dbmi.h>
  20. #include "global.h"
  21. static char first_selection = 1;
  22. static int merge_lists(struct ilist *, struct ilist *);
  23. /**
  24. \brief Select vector features
  25. \param[in] Map vector map
  26. \param[in] action_mode tool
  27. \param[in] params GRASS parameters
  28. \param[in] List list of selected features
  29. \return list of newly selected features
  30. */
  31. struct ilist *select_lines(struct Map_info *Map, enum mode action_mode,
  32. struct GParams *params, double *thresh,
  33. struct ilist *List)
  34. {
  35. int layer, type;
  36. layer = Vect_get_field_number(Map, params->fld->answer);
  37. type = Vect_option_to_types(params->type);
  38. /* select by id's */
  39. if (params->id->answer != NULL) {
  40. sel_by_id(Map, type, params->id->answer, List);
  41. }
  42. /* select by category (ignore tools catdel and catadd) */
  43. if ((action_mode != MODE_CATADD && action_mode != MODE_CATDEL) &&
  44. params->cat->answer != NULL) {
  45. sel_by_cat(Map, NULL, layer, type, params->cat->answer, List);
  46. }
  47. /* select by coordinates (+threshold) */
  48. if (params->coord->answer != NULL) {
  49. int i;
  50. double east, north;
  51. struct line_pnts *coords;
  52. coords = Vect_new_line_struct();
  53. i = 0;
  54. while (params->coord->answers[i]) {
  55. east = atof(params->coord->answers[i]);
  56. north = atof(params->coord->answers[i + 1]);
  57. Vect_append_point(coords, east, north, 0.0);
  58. i += 2;
  59. }
  60. G_verbose_message(_("Threshold value for coordinates is %.2f"),
  61. thresh[THRESH_COORDS]);
  62. sel_by_coordinates(Map, type, coords, thresh[THRESH_COORDS], List);
  63. Vect_destroy_line_struct(coords);
  64. }
  65. /* select by bbox */
  66. if (params->bbox->answer != NULL) {
  67. struct line_pnts *bbox;
  68. double x1, y1, x2, y2;
  69. bbox = Vect_new_line_struct();
  70. x1 = atof(params->bbox->answers[0]);
  71. y1 = atof(params->bbox->answers[1]);
  72. x2 = atof(params->bbox->answers[2]);
  73. y2 = atof(params->bbox->answers[3]);
  74. Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
  75. Vect_append_point(bbox, x2, y1, PORT_DOUBLE_MAX);
  76. Vect_append_point(bbox, x2, y2, -PORT_DOUBLE_MAX);
  77. Vect_append_point(bbox, x1, y2, PORT_DOUBLE_MAX);
  78. Vect_append_point(bbox, x1, y1, -PORT_DOUBLE_MAX);
  79. /* sel_by_bbox not used */
  80. /*
  81. sel_by_bbox(Map,
  82. type, x1, y1, x2, y2,
  83. List);
  84. */
  85. sel_by_polygon(Map, type, bbox, List);
  86. Vect_destroy_line_struct(bbox);
  87. }
  88. /* select by polygon */
  89. if (params->poly->answer != NULL) {
  90. int i;
  91. struct line_pnts *Polygon;
  92. Polygon = Vect_new_line_struct();
  93. for (i = 0; params->poly->answers[i]; i += 2) {
  94. Vect_append_point(Polygon,
  95. atof(params->poly->answers[i]),
  96. atof(params->poly->answers[i + 1]), 0.0);
  97. }
  98. /* if first and last point of polygon does not match */
  99. if (atof(params->poly->answers[i - 1]) !=
  100. atof(params->poly->answers[0])) {
  101. Vect_append_point(Polygon, atof(params->poly->answers[0]),
  102. atof(params->poly->answers[1]), 0.0);
  103. }
  104. sel_by_polygon(Map, type, Polygon, List);
  105. Vect_destroy_line_struct(Polygon);
  106. }
  107. /* select by where statement */
  108. if (params->where->answer != NULL) {
  109. sel_by_where(Map, layer, type, params->where->answer, List);
  110. }
  111. /* selecy by query */
  112. if (params->query->answer != NULL) {
  113. int query_type;
  114. struct ilist *List_tmp;
  115. if (first_selection) {
  116. List_tmp = List;
  117. first_selection = 0;
  118. }
  119. else {
  120. List_tmp = Vect_new_list();
  121. }
  122. query_type = QUERY_UNKNOWN;
  123. if (strcmp(params->query->answer, "length") == 0) {
  124. query_type = QUERY_LENGTH;
  125. }
  126. else if (strcmp(params->query->answer, "dangle") == 0) {
  127. query_type = QUERY_DANGLE;
  128. }
  129. G_verbose_message(_("Threshold value for querying is %.2f"),
  130. thresh[THRESH_QUERY]);
  131. Vedit_select_by_query(Map, type, layer, thresh[THRESH_QUERY],
  132. query_type, List_tmp);
  133. /* merge lists (only duplicate items) */
  134. if (List_tmp != List) {
  135. merge_lists(List, List_tmp);
  136. Vect_destroy_list(List_tmp);
  137. }
  138. }
  139. if (params->reverse->answer) {
  140. reverse_selection(Map, type, &List);
  141. }
  142. G_message(_("%d of %d features selected from vector map <%s>"),
  143. List->n_values,
  144. Vect_get_num_lines(Map), Vect_get_full_name(Map));
  145. return List;
  146. }
  147. /**
  148. \brief Print selected vector features
  149. \param[in] List list of selected features
  150. \return number of selected features
  151. \return -1 on error
  152. */
  153. int print_selected(struct ilist *List)
  154. {
  155. int i;
  156. /* print the result */
  157. for (i = 0; i < List->n_values; i++) {
  158. fprintf(stdout, "%d%s",
  159. List->value[i], i < List->n_values - 1 ? "," : "");
  160. }
  161. if (List->n_values > 0) {
  162. fprintf(stdout, "\n");
  163. }
  164. fflush(stdout);
  165. return List->n_values;
  166. }
  167. /**
  168. \brief Select features by category
  169. \param[in] Map vector map
  170. \param[in] cl_orig original list of categories (previously selected)
  171. \param[in] layer layer number
  172. \param[in] type feature type
  173. \param[in] cat category string
  174. \param[in,out] List list of selected features
  175. \return number of selected lines
  176. */
  177. int sel_by_cat(struct Map_info *Map, struct cat_list *cl_orig,
  178. int layer, int type, char *cats, struct ilist *List)
  179. {
  180. struct ilist *List_tmp, *List_tmp1;
  181. struct cat_list *cl;
  182. int i, cat;
  183. if (first_selection || cl_orig) {
  184. List_tmp = List;
  185. first_selection = 0;
  186. }
  187. else {
  188. List_tmp = Vect_new_list();
  189. }
  190. List_tmp1 = Vect_new_list();
  191. if (cl_orig == NULL) {
  192. cl = Vect_new_cat_list();
  193. Vect_str_to_cat_list(cats, cl);
  194. }
  195. else {
  196. cl = cl_orig;
  197. }
  198. for (i = 0; i < cl->n_ranges; i++) {
  199. for (cat = cl->min[i]; cat <= cl->max[i]; cat++) {
  200. Vect_cidx_find_all(Map, layer, type, cat, List_tmp1);
  201. Vect_list_append_list(List_tmp, List_tmp1);
  202. }
  203. }
  204. G_debug(1, " %d lines selected (by category)", List_tmp->n_values);
  205. /* merge lists (only duplicate items) */
  206. if (List_tmp != List) {
  207. merge_lists(List, List_tmp);
  208. Vect_destroy_list(List_tmp);
  209. }
  210. Vect_destroy_list(List_tmp1);
  211. return List->n_values;
  212. }
  213. /**
  214. \brief Select features by coordinates
  215. \param[in] Map vector map
  216. \param[in] type feature type
  217. \param[in] coords coordinates GRASS parameters
  218. \param[in] thresh threshold value for searching
  219. \param[in,out] List list of selected features
  220. \return number of selected lines
  221. */
  222. int sel_by_coordinates(struct Map_info *Map,
  223. int type, struct line_pnts *coords, double thresh,
  224. struct ilist *List)
  225. {
  226. int i;
  227. double east, north, maxdist;
  228. struct ilist *List_tmp, *List_in_box;
  229. struct line_pnts *box;
  230. if (first_selection) {
  231. List_tmp = List;
  232. first_selection = 0;
  233. }
  234. else {
  235. List_tmp = Vect_new_list();
  236. }
  237. box = Vect_new_line_struct();
  238. List_in_box = Vect_new_list();
  239. if (thresh < 0)
  240. maxdist = max_distance(thresh);
  241. else
  242. maxdist = thresh;
  243. for (i = 0; i < coords->n_points; i++) {
  244. east = coords->x[i];
  245. north = coords->y[i];
  246. coord2bbox(east, north, maxdist, box);
  247. Vect_select_lines_by_polygon(Map, box, 0, NULL, type, List_in_box);
  248. if (List_in_box->n_values > 0)
  249. Vect_list_append_list(List_tmp, List_in_box);
  250. }
  251. G_debug(1, " %d lines selected (by coordinates)", List_tmp->n_values);
  252. /* merge lists (only duplicate items) */
  253. if (List_tmp != List) {
  254. merge_lists(List, List_tmp);
  255. Vect_destroy_list(List_tmp);
  256. }
  257. Vect_destroy_line_struct(box);
  258. Vect_destroy_list(List_in_box);
  259. return List->n_values;
  260. }
  261. /**
  262. \brief Select features by bbox
  263. \param[in] Map vector map
  264. \param[in] type feature type
  265. \param[in] bbox_opt bounding boxes
  266. \param[in,out] List list of selected features
  267. \return number of selected lines
  268. */
  269. int sel_by_bbox(struct Map_info *Map,
  270. int type, double x1, double y1, double x2, double y2,
  271. struct ilist *List)
  272. {
  273. struct bound_box bbox;
  274. struct ilist *List_tmp;
  275. if (first_selection) {
  276. List_tmp = List;
  277. first_selection = 0;
  278. }
  279. else {
  280. List_tmp = Vect_new_list();
  281. }
  282. /* bounding box */
  283. bbox.N = y1 < y2 ? y2 : y1;
  284. bbox.S = y1 < y2 ? y1 : y2;
  285. bbox.W = x1 < x2 ? x1 : x2;
  286. bbox.E = x1 < x2 ? x2 : x1;
  287. bbox.T = PORT_DOUBLE_MAX;
  288. bbox.B = -PORT_DOUBLE_MAX;
  289. Vect_select_lines_by_box(Map, &bbox, type, List_tmp);
  290. G_debug(1, " %d lines selected (by bbox)", List_tmp->n_values);
  291. /* merge lists (only duplicate items) */
  292. if (List_tmp != List) {
  293. merge_lists(List, List_tmp);
  294. Vect_destroy_list(List_tmp);
  295. }
  296. return List->n_values;
  297. }
  298. /**
  299. \brief Select features by polygon
  300. \param[in] Map vector map
  301. \param[in] type feature type
  302. \param[in] poly polygon coordinates
  303. \param[in,out] List list of selected features
  304. \return number of selected lines
  305. */
  306. int sel_by_polygon(struct Map_info *Map,
  307. int type, struct line_pnts *Polygon, struct ilist *List)
  308. {
  309. struct ilist *List_tmp;
  310. if (first_selection) {
  311. List_tmp = List;
  312. first_selection = 0;
  313. }
  314. else {
  315. List_tmp = Vect_new_list();
  316. }
  317. /* no isles */
  318. Vect_select_lines_by_polygon(Map, Polygon, 0, NULL, type, List_tmp);
  319. G_debug(1, " %d lines selected (by polygon)", List_tmp->n_values);
  320. /* merge lists (only duplicate items) */
  321. if (List_tmp != List) {
  322. merge_lists(List, List_tmp);
  323. Vect_destroy_list(List_tmp);
  324. }
  325. return List->n_values;
  326. }
  327. /**
  328. \brief Select features by id
  329. \param[in] Map vector map
  330. \param[in] type feature type
  331. \param[in] ids ids list
  332. \param[in,out] List list of selected features
  333. \return number of selected lines
  334. */
  335. int sel_by_id(struct Map_info *Map, int type, char *ids, struct ilist *List)
  336. {
  337. int i;
  338. int num, id;
  339. struct cat_list *il; /* NOTE: this is not cat list, but list of id's */
  340. struct ilist *List_tmp;
  341. if (first_selection) {
  342. List_tmp = List;
  343. first_selection = 0;
  344. }
  345. else {
  346. List_tmp = Vect_new_list();
  347. }
  348. il = Vect_new_cat_list();
  349. Vect_str_to_cat_list(ids, il);
  350. num = Vect_get_num_lines(Map);
  351. for (i = 0; i < il->n_ranges; i++) {
  352. for (id = 1; id <= num; id++) {
  353. if (!(Vect_read_line(Map, NULL, NULL, id) & type)) {
  354. continue;
  355. }
  356. if (id >= il->min[i] && id <= il->max[i]) {
  357. Vect_list_append(List_tmp, id);
  358. }
  359. }
  360. }
  361. G_debug(1, " %d lines selected (by id)", List_tmp->n_values);
  362. /* merge lists (only duplicate items) */
  363. if (List_tmp != List) {
  364. merge_lists(List, List_tmp);
  365. Vect_destroy_list(List_tmp);
  366. }
  367. Vect_destroy_cat_list(il);
  368. return List->n_values;
  369. }
  370. /**
  371. \brief Select features according to SQL where statement
  372. \param[in] Map vector map
  373. \param[in] layer layer number
  374. \param[in] type feature type
  375. \param[in] where 'where' statement
  376. \param[in,out] List list of selected features
  377. \return number of selected lines
  378. */
  379. int sel_by_where(struct Map_info *Map,
  380. int layer, int type, char *where, struct ilist *List)
  381. {
  382. struct cat_list *cat_list;
  383. struct ilist *List_tmp;
  384. struct field_info *Fi;
  385. dbDriver *driver;
  386. dbHandle handle;
  387. int *cats, ncats;
  388. if (first_selection) {
  389. List_tmp = List;
  390. first_selection = 0;
  391. }
  392. else {
  393. List_tmp = Vect_new_list();
  394. }
  395. cat_list = Vect_new_cat_list();
  396. if (layer < 1) {
  397. G_fatal_error(_("Layer must be > 0 for 'where'"));
  398. }
  399. Fi = Vect_get_field(Map, layer);
  400. if (!Fi) {
  401. G_fatal_error(_("Database connection not defined for layer %d"),
  402. layer);
  403. }
  404. driver = db_start_driver(Fi->driver);
  405. if (!driver)
  406. G_fatal_error(_("Unable to start driver <%s>"), Fi->driver);
  407. db_init_handle(&handle);
  408. db_set_handle(&handle, Fi->database, NULL);
  409. if (db_open_database(driver, &handle) != DB_OK)
  410. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  411. Fi->database, Fi->driver);
  412. ncats = db_select_int(driver, Fi->table, Fi->key, where, &cats);
  413. db_close_database(driver);
  414. db_shutdown_driver(driver);
  415. Vect_array_to_cat_list(cats, ncats, cat_list);
  416. /* free array of cats */
  417. if (ncats >= 0)
  418. G_free(cats);
  419. sel_by_cat(Map, cat_list, layer, type, NULL, List_tmp);
  420. G_debug(1, " %d lines selected (by where)", List_tmp->n_values);
  421. /* merge lists (only duplicate items) */
  422. if (List_tmp != List) {
  423. merge_lists(List, List_tmp);
  424. Vect_destroy_list(List_tmp);
  425. }
  426. Vect_destroy_cat_list(cat_list);
  427. return List->n_values;
  428. }
  429. /**
  430. \brief merge two list, i.e. store only duplicate items
  431. \param[in] alist,blist list to be merged
  432. \return result number of items
  433. */
  434. static int merge_lists(struct ilist *alist, struct ilist *blist)
  435. {
  436. int i;
  437. struct ilist *list_del;
  438. list_del = Vect_new_list();
  439. for (i = 0; i < alist->n_values; i++) {
  440. if (!Vect_val_in_list(blist, alist->value[i]))
  441. Vect_list_append(list_del, alist->value[i]);
  442. }
  443. Vect_list_delete_list(alist, list_del);
  444. Vect_destroy_list(list_del);
  445. return alist->n_values;
  446. }
  447. /**
  448. \brief Reverse list selection
  449. \param[in] Map vector map
  450. \param[in] type feature type
  451. \param[in,out] reversed list
  452. \return 1
  453. */
  454. int reverse_selection(struct Map_info *Map, int type, struct ilist **List)
  455. {
  456. struct ilist *list_reverse;
  457. int line, nlines, ltype;
  458. list_reverse = Vect_new_list();
  459. nlines = Vect_get_num_lines(Map);
  460. for (line = 1; line <= nlines; line++) {
  461. ltype = Vect_read_line(Map, NULL, NULL, line);
  462. if (!(ltype & type))
  463. continue;
  464. if (!Vect_val_in_list(*List, line))
  465. Vect_list_append(list_reverse, line);
  466. }
  467. Vect_destroy_list(*List);
  468. *List = list_reverse;
  469. return 1;
  470. }