main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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-2010 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General
  13. * Public License (>=v2). Read the file COPYING that
  14. * comes with GRASS for details.
  15. *
  16. * TODO: 3D support (done for move and vertexmove)
  17. ****************************************************************/
  18. #include "global.h"
  19. int main(int argc, char *argv[])
  20. {
  21. struct GModule *module;
  22. struct GParams params;
  23. struct Map_info Map;
  24. struct Map_info **BgMap; /* backgroud vector maps */
  25. int nbgmaps; /* number of registrated background maps */
  26. enum mode action_mode;
  27. FILE *ascii;
  28. int i;
  29. int move_first, snap;
  30. int ret, print, layer;
  31. double move_x, move_y, move_z, thresh[3];
  32. struct line_pnts *coord;
  33. struct ilist *List;
  34. struct cat_list *Clist;
  35. ascii = NULL;
  36. List = NULL;
  37. BgMap = NULL;
  38. nbgmaps = 0;
  39. coord = NULL;
  40. Clist = NULL;
  41. G_gisinit(argv[0]);
  42. module = G_define_module();
  43. G_add_keyword(_("vector"));
  44. G_add_keyword(_("editing"));
  45. G_add_keyword(_("geometry"));
  46. module->description = _("Edits a vector map, allows adding, deleting "
  47. "and modifying selected vector features.");
  48. if (!parser(argc, argv, &params, &action_mode))
  49. exit(EXIT_FAILURE);
  50. /* get list of categories */
  51. Clist = Vect_new_cat_list();
  52. if (params.cat->answer && Vect_str_to_cat_list(params.cat->answer, Clist)) {
  53. G_fatal_error(_("Unable to get category list <%s>"),
  54. params.cat->answer);
  55. }
  56. /* open input file */
  57. if (G_strcasecmp(params.in->answer, "-") == 0 ||
  58. (action_mode != MODE_CREATE && params.in->answer == NULL)) {
  59. ascii = stdin;
  60. }
  61. else if (params.in->answer) {
  62. ascii = fopen(params.in->answer, "r");
  63. if (ascii == NULL) {
  64. G_fatal_error(_("Unable to open ASCII file <%s>"),
  65. params.in->answer);
  66. }
  67. }
  68. if (action_mode == MODE_CREATE) {
  69. int overwrite;
  70. overwrite = G_check_overwrite(argc, argv);
  71. if (G_find_vector2(params.map->answer, G_mapset())) {
  72. if (!overwrite)
  73. G_fatal_error(_("Vector map <%s> already exists"),
  74. params.map->answer);
  75. }
  76. /* 3D vector maps? */
  77. ret = Vect_open_new(&Map, params.map->answer, WITHOUT_Z);
  78. if (ret == -1) {
  79. G_fatal_error(_("Unable to create vector map <%s>"),
  80. params.map->answer);
  81. }
  82. G_debug(1, "Map created");
  83. if (ascii) {
  84. /* also add new vector features */
  85. action_mode = MODE_ADD;
  86. }
  87. }
  88. else { /* open selected vector file */
  89. if (action_mode == MODE_ADD) /* write */
  90. ret = Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
  91. else /* read-only -- select features */
  92. ret = Vect_open_old2(&Map, params.map->answer, G_mapset(), params.fld->answer);
  93. if (ret < 2)
  94. G_fatal_error(_("Unable to open vector map <%s> at topological level %d"),
  95. params.map->answer, 2);
  96. }
  97. G_debug(1, "Map opened");
  98. /* open backgroud maps */
  99. if (params.bmaps->answer) {
  100. i = 0;
  101. while (params.bmaps->answers[i]) {
  102. const char *bmap = params.bmaps->answers[i];
  103. const char *mapset = G_find_vector2(bmap, "");
  104. if (!mapset)
  105. G_fatal_error(_("Vector map <%s> not found"), bmap);
  106. if (strcmp(
  107. G_fully_qualified_name(params.map->answer, G_mapset()),
  108. G_fully_qualified_name(bmap, mapset)) == 0) {
  109. G_fatal_error(_("Unable to open vector map <%s> as the background map. "
  110. "It is given as vector map to be edited."),
  111. bmap);
  112. }
  113. nbgmaps++;
  114. BgMap = (struct Map_info **)G_realloc(
  115. BgMap, nbgmaps * sizeof(struct Map_info *));
  116. BgMap[nbgmaps - 1] =
  117. (struct Map_info *)G_malloc(sizeof(struct Map_info));
  118. if (Vect_open_old(BgMap[nbgmaps - 1], bmap, "") == -1)
  119. G_fatal_error(_("Unable to open vector map <%s>"), bmap);
  120. G_verbose_message(_("Background vector map <%s> registered"), bmap);
  121. i++;
  122. }
  123. }
  124. layer = Vect_get_field_number(&Map, params.fld->answer);
  125. i = 0;
  126. while (params.maxdist->answers[i]) {
  127. switch (i) {
  128. case THRESH_COORDS:
  129. thresh[THRESH_COORDS] =
  130. max_distance(atof(params.maxdist->answers[THRESH_COORDS]));
  131. thresh[THRESH_SNAP] = thresh[THRESH_QUERY] =
  132. thresh[THRESH_COORDS];
  133. break;
  134. case THRESH_SNAP:
  135. thresh[THRESH_SNAP] =
  136. max_distance(atof(params.maxdist->answers[THRESH_SNAP]));
  137. break;
  138. case THRESH_QUERY:
  139. thresh[THRESH_QUERY] =
  140. atof(params.maxdist->answers[THRESH_QUERY]);
  141. break;
  142. default:
  143. break;
  144. }
  145. i++;
  146. }
  147. move_first = params.move_first->answer ? 1 : 0;
  148. snap = NO_SNAP;
  149. if (strcmp(params.snap->answer, "node") == 0)
  150. snap = SNAP;
  151. else if (strcmp(params.snap->answer, "vertex") == 0)
  152. snap = SNAPVERTEX;
  153. if (action_mode != MODE_CREATE && action_mode != MODE_ADD) {
  154. /* select lines */
  155. List = Vect_new_list();
  156. G_message(_("Selecting features..."));
  157. if (action_mode == MODE_COPY && BgMap && BgMap[0]) {
  158. List = select_lines(BgMap[0], action_mode, &params, thresh, List);
  159. }
  160. else {
  161. List = select_lines(&Map, action_mode, &params, thresh, List);
  162. }
  163. }
  164. if ((action_mode != MODE_CREATE && action_mode != MODE_ADD &&
  165. action_mode != MODE_SELECT)) {
  166. if (List->n_values < 1) {
  167. G_warning(_("No features selected, nothing to edit"));
  168. action_mode = MODE_NONE;
  169. ret = 0;
  170. }
  171. else {
  172. /* reopen the map for updating */
  173. if (action_mode == MODE_ZBULK && !Vect_is_3d(&Map)) {
  174. Vect_close(&Map);
  175. G_fatal_error(_("Vector map <%s> is not 3D. Tool '%s' requires 3D vector map. "
  176. "Please convert the vector map "
  177. "to 3D using e.g. %s."), params.map->answer,
  178. params.tool->answer, "v.extrude");
  179. }
  180. Vect_close(&Map);
  181. Vect_open_update2(&Map, params.map->answer, G_mapset(), params.fld->answer);
  182. }
  183. }
  184. /* coords option -> array */
  185. if (params.coord->answers) {
  186. coord = Vect_new_line_struct();
  187. int i = 0;
  188. double east, north;
  189. while (params.coord->answers[i]) {
  190. east = atof(params.coord->answers[i]);
  191. north = atof(params.coord->answers[i + 1]);
  192. Vect_append_point(coord, east, north, 0.0);
  193. i += 2;
  194. }
  195. }
  196. /* perform requested editation */
  197. switch (action_mode) {
  198. case MODE_CREATE:
  199. print = 0; /* do not print id's */
  200. break;
  201. case MODE_ADD:
  202. print = 0;
  203. if (!params.header->answer)
  204. Vect_read_ascii_head(ascii, &Map);
  205. int num_lines;
  206. num_lines = Vect_get_num_lines(&Map);
  207. ret = Vect_read_ascii(ascii, &Map);
  208. G_message(_("%d features added"), ret);
  209. if (ret > 0) {
  210. int iline;
  211. struct ilist *List_added;
  212. List_added = Vect_new_list();
  213. for (iline = num_lines + 1; iline <= Vect_get_num_lines(&Map); iline++)
  214. Vect_list_append(List_added, iline);
  215. G_verbose_message(_("Threshold value for snapping is %.2f"),
  216. thresh[THRESH_SNAP]);
  217. if (snap != NO_SNAP) { /* apply snapping */
  218. Vedit_snap_lines(&Map, BgMap, nbgmaps, List_added, thresh[THRESH_SNAP], snap == SNAP ? 0 : 1); /* snap to vertex ? */
  219. }
  220. if (params.close->answer) { /* close boundaries */
  221. int nclosed;
  222. nclosed = close_lines(&Map, GV_BOUNDARY, thresh[THRESH_SNAP]);
  223. G_message(_("%d boundaries closed"), nclosed);
  224. }
  225. Vect_destroy_list(List_added);
  226. }
  227. break;
  228. case MODE_DEL:
  229. ret = Vedit_delete_lines(&Map, List);
  230. G_message(_("%d features deleted"), ret);
  231. break;
  232. case MODE_MOVE:
  233. move_x = atof(params.move->answers[0]);
  234. move_y = atof(params.move->answers[1]);
  235. move_z = atof(params.move->answers[2]);
  236. G_verbose_message(_("Threshold value for snapping is %.2f"),
  237. thresh[THRESH_SNAP]);
  238. ret = Vedit_move_lines(&Map, BgMap, nbgmaps, List, move_x, move_y, move_z, snap, thresh[THRESH_SNAP]);
  239. G_message(_("%d features moved"), ret);
  240. break;
  241. case MODE_VERTEX_MOVE:
  242. move_x = atof(params.move->answers[0]);
  243. move_y = atof(params.move->answers[1]);
  244. move_z = atof(params.move->answers[2]);
  245. G_verbose_message(_("Threshold value for snapping is %.2f"),
  246. thresh[THRESH_SNAP]);
  247. ret = Vedit_move_vertex(&Map, BgMap, nbgmaps, List, coord, thresh[THRESH_COORDS], thresh[THRESH_SNAP], move_x, move_y, move_z, move_first, snap);
  248. G_message(_("%d vertices moved"), ret);
  249. break;
  250. case MODE_VERTEX_ADD:
  251. ret = Vedit_add_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
  252. G_message(_("%d vertices added"), ret);
  253. break;
  254. case MODE_VERTEX_DELETE:
  255. ret = Vedit_remove_vertex(&Map, List, coord, thresh[THRESH_COORDS]);
  256. G_message(_("%d vertices removed"), ret);
  257. break;
  258. case MODE_BREAK:
  259. if (params.coord->answer) {
  260. ret = Vedit_split_lines(&Map, List,
  261. coord, thresh[THRESH_COORDS], NULL);
  262. }
  263. else {
  264. ret = Vect_break_lines_list(&Map, List, NULL, GV_LINES, NULL);
  265. }
  266. G_message(_("%d lines broken"), ret);
  267. break;
  268. case MODE_CONNECT:
  269. G_verbose_message(_("Threshold value for snapping is %.2f"),
  270. thresh[THRESH_SNAP]);
  271. ret = Vedit_connect_lines(&Map, List, thresh[THRESH_SNAP]);
  272. G_message(_("%d lines connected"), ret);
  273. break;
  274. case MODE_MERGE:
  275. ret = Vedit_merge_lines(&Map, List);
  276. G_message(_("%d lines merged"), ret);
  277. break;
  278. case MODE_SELECT:
  279. print = 1;
  280. ret = print_selected(List);
  281. break;
  282. case MODE_CATADD:
  283. ret = Vedit_modify_cats(&Map, List, layer, 0, Clist);
  284. G_message(_("%d features modified"), ret);
  285. break;
  286. case MODE_CATDEL:
  287. ret = Vedit_modify_cats(&Map, List, layer, 1, Clist);
  288. G_message(_("%d features modified"), ret);
  289. break;
  290. case MODE_COPY:
  291. if (BgMap && BgMap[0]) {
  292. if (nbgmaps > 1)
  293. G_warning(_("Multiple background maps were given. "
  294. "Selected features will be copied only from "
  295. "vector map <%s>."),
  296. Vect_get_full_name(BgMap[0]));
  297. ret = Vedit_copy_lines(&Map, BgMap[0], List);
  298. }
  299. else {
  300. ret = Vedit_copy_lines(&Map, NULL, List);
  301. }
  302. G_message(_("%d features copied"), ret);
  303. break;
  304. case MODE_SNAP:
  305. G_verbose_message(_("Threshold value for snapping is %.2f"),
  306. thresh[THRESH_SNAP]);
  307. ret = snap_lines(&Map, List, thresh[THRESH_SNAP]);
  308. break;
  309. case MODE_FLIP:
  310. ret = Vedit_flip_lines(&Map, List);
  311. G_message(_("%d lines flipped"), ret);
  312. break;
  313. case MODE_NONE:
  314. print = 0;
  315. break;
  316. case MODE_ZBULK:{
  317. double start, step;
  318. double x1, y1, x2, y2;
  319. start = atof(params.zbulk->answers[0]);
  320. step = atof(params.zbulk->answers[1]);
  321. x1 = atof(params.bbox->answers[0]);
  322. y1 = atof(params.bbox->answers[1]);
  323. x2 = atof(params.bbox->answers[2]);
  324. y2 = atof(params.bbox->answers[3]);
  325. ret = Vedit_bulk_labeling(&Map, List,
  326. x1, y1, x2, y2, start, step);
  327. G_message(_("%d lines labeled"), ret);
  328. break;
  329. }
  330. case MODE_CHTYPE:{
  331. ret = Vedit_chtype_lines(&Map, List);
  332. if (ret > 0) {
  333. G_message(_("%d features converted"), ret);
  334. }
  335. else {
  336. G_message(_("No feature modified"));
  337. }
  338. break;
  339. }
  340. default:
  341. G_warning(_("Operation not implemented"));
  342. ret = -1;
  343. break;
  344. }
  345. Vect_hist_command(&Map);
  346. /* build topology only if requested or if tool!=select */
  347. if (!(action_mode == MODE_SELECT || params.topo->answer == 1 ||
  348. !MODE_NONE)) {
  349. Vect_build_partial(&Map, GV_BUILD_NONE);
  350. Vect_build(&Map);
  351. }
  352. if (List)
  353. Vect_destroy_list(List);
  354. Vect_close(&Map);
  355. G_debug(1, "Map closed");
  356. /* close background maps */
  357. for (i = 0; i < nbgmaps; i++) {
  358. Vect_close(BgMap[i]);
  359. G_free((void *)BgMap[i]);
  360. }
  361. G_free((void *)BgMap);
  362. if (coord)
  363. Vect_destroy_line_struct(coord);
  364. if (Clist)
  365. Vect_destroy_cat_list(Clist);
  366. G_done_msg(" ");
  367. if (ret > -1) {
  368. exit(EXIT_SUCCESS);
  369. }
  370. else {
  371. exit(EXIT_FAILURE);
  372. }
  373. }