line.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /**
  2. \file line.cpp
  3. \brief wxvdigit - Feature manipulation (add, delete, move)
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. (C) 2008-2009 by Martin Landa, and the GRASS development team
  8. \author Martin Landa <landa.martin gmail.com>
  9. */
  10. extern "C" {
  11. #include <grass/vedit.h>
  12. #include <grass/dbmi.h>
  13. }
  14. #include "driver.h"
  15. #include "digit.h"
  16. /**
  17. \brief Add new vector feature
  18. \param type feature type
  19. \param coords pairs of coordinates list (2D or 3D map)
  20. \param layer layer number (layer < 1 -> no category)
  21. \param cat category number
  22. \param bgmap map of background map or NULL
  23. \param snap snapping mode (see vedit.h)
  24. \param thresh threshold value for snapping
  25. \return fid on success
  26. \return -1 on failure
  27. */
  28. int Digit::AddLine(int type, std::vector<double> coords, int layer, int cat,
  29. const char *bgmap, int snap, double threshold)
  30. {
  31. size_t i;
  32. size_t npoints;
  33. int newline;
  34. int changeset;
  35. struct line_pnts *Points;
  36. struct line_cats *Cats;
  37. struct Map_info **BgMap; /* backgroud vector maps */
  38. int nbgmaps; /* number of registrated background maps */
  39. if (!display->mapInfo) {
  40. display->DisplayMsg();
  41. return -1;
  42. }
  43. npoints = coords.size() / (Vect_is_3d(display->mapInfo) ? 3 : 2);
  44. if (coords.size() != npoints * (Vect_is_3d(display->mapInfo) ? 3 : 2)) {
  45. wxString msg;
  46. msg.Printf(_("Incorrent number of points (%d)"), coords.size());
  47. wxMessageDialog dlg(display->parentWin, msg,
  48. display->msgCaption, wxOK | wxICON_ERROR | wxCENTRE);
  49. dlg.ShowModal();
  50. return -1;
  51. }
  52. G_debug(2, "wxDigit.AddLine(): npoints=%d, layer=%d, cat=%d, snap=%d",
  53. (int) npoints, layer, cat, snap);
  54. /* TODO: 3D */
  55. if (!(type & (GV_POINTS | GV_LINES))) {
  56. display->Only2DMsg();
  57. return -1;
  58. }
  59. BgMap = NULL;
  60. nbgmaps = 0;
  61. if (bgmap && strlen(bgmap) > 0) {
  62. BgMap = OpenBackgroundVectorMap(bgmap);
  63. if (!BgMap) {
  64. display->BackgroundMapMsg(bgmap);
  65. return -1;
  66. }
  67. else {
  68. nbgmaps = 1;
  69. }
  70. }
  71. Points = Vect_new_line_struct();
  72. Cats = Vect_new_cats_struct();
  73. if (layer > 0) {
  74. Vect_cat_set(Cats, layer, cat);
  75. if (cat > GetCategory(layer)) {
  76. SetCategory(layer, cat); /* set up max category for layer */
  77. }
  78. }
  79. i = 0;
  80. while (i < coords.size()) {
  81. if (Vect_is_3d(display->mapInfo)) {
  82. Vect_append_point(Points, coords[i], coords[i+1], coords[i+2]);
  83. i += 3;
  84. }
  85. else {
  86. Vect_append_point(Points, coords[i], coords[i+1], 0.0);
  87. i += 2;
  88. }
  89. }
  90. if (type & GV_BOUNDARY) { /* close boundary */
  91. int last = Points->n_points-1;
  92. if (Vect_points_distance(Points->x[0], Points->x[0], Points->z[0],
  93. Points->x[last], Points->x[last], Points->z[last],
  94. Vect_is_3d(display->mapInfo)) <= threshold) {
  95. Points->x[last] = Points->x[0];
  96. Points->y[last] = Points->y[0];
  97. Points->z[last] = Points->z[0];
  98. G_debug(3, "wxDigit.AddLine(): boundary closed");
  99. }
  100. }
  101. if (snap != NO_SNAP && (type & (GV_POINT | GV_LINES))) { /* apply snapping (node or vertex) */
  102. Vedit_snap_line(display->mapInfo, BgMap, nbgmaps,
  103. -1, Points,
  104. threshold, (snap == SNAP) ? 0 : 1);
  105. }
  106. newline = Vect_write_line(display->mapInfo, type, Points, Cats);
  107. if (newline < 0) {
  108. display->WriteLineMsg();
  109. return -1;
  110. }
  111. /* register changeset */
  112. changeset = changesets.size();
  113. AddActionToChangeset(changeset, ADD, newline);
  114. /* break at intersection */
  115. if (settings.breakLines) {
  116. BreakLineAtIntersection(newline, Points, changeset);
  117. }
  118. Vect_destroy_line_struct(Points);
  119. Vect_destroy_cats_struct(Cats);
  120. if (BgMap && BgMap[0]) {
  121. Vect_close(BgMap[0]);
  122. }
  123. return newline;
  124. }
  125. /**
  126. \brief Rewrite given line
  127. \param line line id
  128. \param coords line geometry
  129. \param bgmap map of background map or NULL
  130. \param snap snapping mode (see vedit.h)
  131. \param thresh threshold value for snapping
  132. \return new line id
  133. \return -1 error
  134. */
  135. int Digit::RewriteLine(int line, std::vector<double> coords,
  136. const char *bgmap, int snap, double threshold)
  137. {
  138. int newline, type, dim;
  139. int nlines, changeset;
  140. struct line_pnts *points;
  141. struct line_cats *cats;
  142. struct Map_info **BgMap; /* backgroud vector maps */
  143. int nbgmaps; /* number of registrated background maps */
  144. if (!display->mapInfo) {
  145. display->DisplayMsg();
  146. return -1;
  147. }
  148. /* line alive ? */
  149. if (!Vect_line_alive(display->mapInfo, line)) {
  150. display->WriteLineMsg();
  151. return -1;
  152. }
  153. BgMap = NULL;
  154. nbgmaps = 0;
  155. if (bgmap && strlen(bgmap) > 0) {
  156. BgMap = OpenBackgroundVectorMap(bgmap);
  157. if (!BgMap) {
  158. display->BackgroundMapMsg(bgmap);
  159. return -1;
  160. }
  161. else {
  162. nbgmaps = 1;
  163. }
  164. }
  165. cats = Vect_new_cats_struct();
  166. /* read line */
  167. type = Vect_read_line(display->mapInfo, NULL, cats, line);
  168. if (type < 0) {
  169. Vect_destroy_cats_struct(cats);
  170. if (BgMap && BgMap[0]) {
  171. Vect_close(BgMap[0]);
  172. }
  173. display->ReadLineMsg(line);
  174. return -1;
  175. }
  176. points = Vect_new_line_struct();
  177. /* define line geometry */
  178. if (Vect_is_3d(display->mapInfo)) {
  179. dim = 3;
  180. }
  181. else {
  182. dim = 2;
  183. }
  184. for(size_t i = dim - 1; i < coords.size(); i += dim) {
  185. if (dim == 2) {
  186. Vect_append_point(points, coords[i-1], coords[i], 0.0);
  187. }
  188. else {
  189. Vect_append_point(points, coords[i-2], coords[i-1], coords[i]);
  190. }
  191. }
  192. if (snap != NO_SNAP) { /* apply snapping (node or vertex) */
  193. Vedit_snap_line(display->mapInfo, BgMap, nbgmaps,
  194. -1, points,
  195. threshold, (snap == SNAP) ? 0 : 1);
  196. }
  197. nlines = Vect_get_num_lines(display->mapInfo);
  198. /* register changeset */
  199. changeset = changesets.size();
  200. AddActionToChangeset(changeset, DEL, line);
  201. /* rewrite line */
  202. newline = Vect_rewrite_line(display->mapInfo, line, type, points, cats);
  203. AddActionToChangeset(changeset, ADD, newline);
  204. if (newline > 0 && settings.breakLines) {
  205. BreakLineAtIntersection(newline, points, changeset);
  206. }
  207. if (newline < 0)
  208. display->WriteLineMsg();
  209. Vect_destroy_line_struct(points);
  210. Vect_destroy_cats_struct(cats);
  211. if (BgMap && BgMap[0]) {
  212. Vect_close(BgMap[0]);
  213. }
  214. return newline;
  215. }
  216. /**
  217. \brief Split/break selected line
  218. Shape of line is not changed.
  219. \param x,y,z coordinates (z is used only if map is 3d)
  220. \param thresh threshold value to find a point on line
  221. \return number of modified lines
  222. \return -1 on error
  223. */
  224. int Digit::SplitLine(double x, double y, double z,
  225. double thresh)
  226. {
  227. int ret;
  228. int nlines, changeset;
  229. struct line_pnts *point;
  230. struct ilist *list;
  231. if (!display->mapInfo) {
  232. display->DisplayMsg();
  233. return -1;
  234. }
  235. point = Vect_new_line_struct();
  236. list = Vect_new_list();
  237. Vect_append_point(point, x, y, z);
  238. nlines = Vect_get_num_lines(display->mapInfo);
  239. changeset = AddActionsBefore();
  240. ret = Vedit_split_lines(display->mapInfo, display->selected.ids,
  241. point, thresh, list);
  242. if (ret > 0) {
  243. AddActionsAfter(changeset, nlines);
  244. }
  245. else {
  246. changesets.erase(changeset);
  247. }
  248. Vect_destroy_list(list);
  249. Vect_destroy_line_struct(point);
  250. return ret;
  251. }
  252. /**
  253. \brief Delete selected vector features
  254. \param delete_records delete also attribute records
  255. \return number of deleted lines
  256. \return -1 on error
  257. */
  258. int Digit::DeleteLines(bool delete_records)
  259. {
  260. int ret;
  261. int n_dblinks;
  262. int changeset;
  263. struct line_cats *Cats, *Cats_del;
  264. if (!display->mapInfo) {
  265. display->DisplayMsg();
  266. return -1;
  267. }
  268. n_dblinks = Vect_get_num_dblinks(display->mapInfo);
  269. Cats_del = NULL;
  270. /* collect categories if needed */
  271. if (delete_records) {
  272. Cats = Vect_new_cats_struct();
  273. Cats_del = Vect_new_cats_struct();
  274. for (int i = 0; i < display->selected.ids->n_values; i++) {
  275. if (Vect_read_line(display->mapInfo, NULL, Cats, display->selected.ids->value[i]) < 0) {
  276. Vect_destroy_cats_struct(Cats_del);
  277. display->ReadLineMsg(display->selected.ids->value[i]);
  278. return -1;
  279. }
  280. for (int j = 0; j < Cats->n_cats; j++) {
  281. /*
  282. To find other vector objects with the same category,
  283. category index is need to be updated (i.e. to
  284. rebuild topo, sidx, cidx). This can be time-consuming
  285. task for large vector maps.
  286. */
  287. /*
  288. Vect_build(display->mapInfo, NULL);
  289. Vect_cidx_find_all(display->mapInfo, Cats->field[j],
  290. GV_POINTS | GV_LINES, Cats->cat[j],
  291. List);
  292. if (List->n_values == 1 &&
  293. List->value[0] == display->selected->value[i]) {
  294. Vect_cat_set(Cats_del, Cats->field[j], Cats->cat[j]);
  295. }
  296. */
  297. Vect_cat_set(Cats_del, Cats->field[j], Cats->cat[j]);
  298. }
  299. }
  300. Vect_destroy_cats_struct(Cats);
  301. }
  302. /* register changeset */
  303. changeset = AddActionsBefore();
  304. ret = Vedit_delete_lines(display->mapInfo, display->selected.ids);
  305. Vect_reset_list(display->selected.ids);
  306. if (ret > 0 && delete_records) {
  307. struct field_info *fi;
  308. char buf[GSQL_MAX];
  309. dbDriver *driver;
  310. dbHandle handle;
  311. dbString stmt;
  312. for (int dblink = 0; dblink < n_dblinks; dblink++) {
  313. fi = Vect_get_dblink(display->mapInfo, dblink);
  314. if (fi == NULL) {
  315. display->DblinkMsg(dblink+1);
  316. return -1;
  317. }
  318. driver = db_start_driver(fi->driver);
  319. if (driver == NULL) {
  320. display->DbDriverMsg(fi->driver);
  321. return -1;
  322. }
  323. db_init_handle (&handle);
  324. db_set_handle (&handle, fi->database, NULL);
  325. if (db_open_database(driver, &handle) != DB_OK) {
  326. display->DbDatabaseMsg(fi->driver, fi->database);
  327. return -1;
  328. }
  329. db_init_string (&stmt);
  330. sprintf (buf, "DELETE FROM %s WHERE", fi->table);
  331. db_set_string(&stmt, buf);
  332. int n_cats = 0;
  333. for (int c = 0; c < Cats_del->n_cats; c++) {
  334. if (Cats_del->field[c] == fi->number) {
  335. if (n_cats > 0) {
  336. sprintf (buf, " or");
  337. db_append_string(&stmt, buf);
  338. }
  339. sprintf (buf, " %s = %d", fi->key, Cats_del->cat[c]);
  340. db_append_string(&stmt, buf);
  341. n_cats++;
  342. }
  343. }
  344. Vect_cat_del(Cats_del, fi->number);
  345. if (n_cats &&
  346. db_execute_immediate (driver, &stmt) != DB_OK ) {
  347. display->DbExecuteMsg(db_get_string(&stmt));
  348. return -1;
  349. }
  350. db_close_database(driver);
  351. db_shutdown_driver(driver);
  352. }
  353. }
  354. /* update category settings */
  355. // InitCats();
  356. if (Cats_del) {
  357. Vect_destroy_cats_struct(Cats_del);
  358. }
  359. return ret;
  360. }
  361. /**
  362. \brief Move selected vector features
  363. \param move_x,move_y,move_z move direction (move_z is used only if map is 3D)
  364. \param bgmap map of background map or NULL
  365. \param snap snapping move (see vedit.h)
  366. \param thresh threshold value for snapping
  367. \return number of moved features
  368. \return -1 on error
  369. */
  370. int Digit::MoveLines(double move_x, double move_y, double move_z,
  371. const char *bgmap, int snap, double thresh)
  372. {
  373. int ret;
  374. int nlines, changeset;
  375. struct Map_info **BgMap; /* backgroud vector maps */
  376. int nbgmaps; /* number of registrated background maps */
  377. if (!display->mapInfo) {
  378. display->DisplayMsg();
  379. return -1;
  380. }
  381. BgMap = NULL;
  382. nbgmaps = 0;
  383. if (bgmap && strlen(bgmap) > 0) {
  384. BgMap = OpenBackgroundVectorMap(bgmap);
  385. if (!BgMap) {
  386. display->BackgroundMapMsg(bgmap);
  387. return -1;
  388. }
  389. else {
  390. nbgmaps = 1;
  391. }
  392. }
  393. nlines = Vect_get_num_lines(display->mapInfo);
  394. /* register changeset */
  395. changeset = AddActionsBefore();
  396. ret = Vedit_move_lines(display->mapInfo, BgMap, nbgmaps,
  397. display->selected.ids,
  398. move_x, move_y, move_z,
  399. snap, thresh);
  400. if (ret > 0) {
  401. AddActionsAfter(changeset, nlines);
  402. }
  403. else {
  404. changesets.erase(changeset);
  405. }
  406. if (ret > 0 && settings.breakLines) {
  407. for(int i = 1; i <= ret; i++) {
  408. BreakLineAtIntersection(nlines + i, NULL, changeset);
  409. }
  410. }
  411. if (BgMap && BgMap[0]) {
  412. Vect_close(BgMap[0]);
  413. }
  414. return ret;
  415. }
  416. /**
  417. \brief Flip selected lines/boundaries
  418. \return number of modified lines
  419. \return -1 on error
  420. */
  421. int Digit::FlipLines()
  422. {
  423. int ret;
  424. int changeset, nlines;
  425. if (!display->mapInfo) {
  426. display->DisplayMsg();
  427. return -1;
  428. }
  429. nlines = Vect_get_num_lines(display->mapInfo);
  430. /* register changeset */
  431. changeset = AddActionsBefore();
  432. ret = Vedit_flip_lines(display->mapInfo, display->selected.ids);
  433. if (ret > 0) {
  434. AddActionsAfter(changeset, nlines);
  435. }
  436. else {
  437. changesets.erase(changeset);
  438. }
  439. return ret;
  440. }
  441. /**
  442. \brief Merge selected lines/boundaries
  443. \return number of modified lines
  444. \return -1 on error
  445. */
  446. int Digit::MergeLines()
  447. {
  448. int ret;
  449. int changeset, nlines;
  450. if (!display->mapInfo) {
  451. display->DisplayMsg();
  452. return -1;
  453. }
  454. nlines = Vect_get_num_lines(display->mapInfo);
  455. changeset = AddActionsBefore();
  456. ret = Vedit_merge_lines(display->mapInfo, display->selected.ids);
  457. if (ret > 0) {
  458. AddActionsAfter(changeset, nlines);
  459. }
  460. else {
  461. changesets.erase(changeset);
  462. }
  463. return ret;
  464. }
  465. /**
  466. \brief Breaks selected lines/boundaries
  467. \todo undo
  468. \return number of modified lines
  469. \return -1 on error
  470. */
  471. int Digit::BreakLines()
  472. {
  473. int ret;
  474. int changeset, nlines;
  475. if (!display->mapInfo) {
  476. display->DisplayMsg();
  477. return -1;
  478. }
  479. nlines = Vect_get_num_lines(display->mapInfo);
  480. changeset = AddActionsBefore();
  481. ret = Vect_break_lines_list(display->mapInfo, display->selected.ids, NULL,
  482. GV_LINES, NULL);
  483. if (ret > 0) {
  484. AddActionsAfter(changeset, nlines);
  485. }
  486. else {
  487. changesets.erase(changeset);
  488. }
  489. return ret;
  490. }
  491. /**
  492. \brief Snap selected lines/boundaries
  493. \todo undo
  494. \param thresh threshold value for snapping
  495. \return 0 on success
  496. \return -1 on error
  497. */
  498. int Digit::SnapLines(double thresh)
  499. {
  500. int changeset, nlines;
  501. if (!display->mapInfo) {
  502. display->DisplayMsg();
  503. return -1;
  504. }
  505. nlines = Vect_get_num_lines(display->mapInfo);
  506. changeset = AddActionsBefore();
  507. Vect_snap_lines_list (display->mapInfo, display->selected.ids,
  508. thresh, NULL);
  509. if (nlines < Vect_get_num_lines(display->mapInfo)) {
  510. AddActionsAfter(changeset, nlines);
  511. }
  512. else {
  513. changesets.erase(changeset);
  514. }
  515. return 0;
  516. }
  517. /**
  518. \brief Connect selected lines/boundaries
  519. \return number of modified lines
  520. \return -1 on error
  521. */
  522. int Digit::ConnectLines(double thresh)
  523. {
  524. int ret;
  525. int changeset, nlines;
  526. if (!display->mapInfo) {
  527. display->DisplayMsg();
  528. return -1;
  529. }
  530. nlines = Vect_get_num_lines(display->mapInfo);
  531. /* register changeset */
  532. changeset = AddActionsBefore();
  533. ret = Vedit_connect_lines(display->mapInfo, display->selected.ids,
  534. thresh);
  535. if (ret > 0) {
  536. AddActionsAfter(changeset, nlines);
  537. }
  538. else {
  539. changesets.erase(changeset);
  540. }
  541. return ret;
  542. }
  543. /**
  544. \brief Automated labeling (z coordinate assignment) of vector lines (contours).
  545. Modified vector map must be 3D.
  546. \todo Undo
  547. \param x1,y1,x2,y2 line nodes for intersection
  548. \param start starting value
  549. \param step step value for labeling
  550. \return number of modified lines
  551. \return -1 on error
  552. */
  553. int Digit::ZBulkLabeling(double x1, double y1, double x2, double y2,
  554. double start, double step)
  555. {
  556. int ret;
  557. int changeset, nlines;
  558. if (!display->mapInfo) {
  559. display->DisplayMsg();
  560. return -1;
  561. }
  562. nlines = Vect_get_num_lines(display->mapInfo);
  563. /* register changeset */
  564. changeset = AddActionsBefore();
  565. ret = Vedit_bulk_labeling (display->mapInfo, display->selected.ids,
  566. x1, y1, x2, y2, start, step);
  567. if (ret > 0) {
  568. AddActionsAfter(changeset, nlines);
  569. }
  570. else {
  571. changesets.erase(changeset);
  572. }
  573. return ret;
  574. }
  575. /**
  576. \brief Copy vector features
  577. \param ids line ids to be copied (if not given selected are used)
  578. \param bgmap name of background map (if not given, copy features from input)
  579. \return number of copied features
  580. \return -1 on error
  581. */
  582. int Digit::CopyLines(std::vector<int> ids, const char* bgmap_name)
  583. {
  584. int ret;
  585. int changeset, nlines;
  586. struct Map_info *bgMap;
  587. struct ilist *list;
  588. bgMap = NULL;
  589. list = NULL;
  590. if (!display->mapInfo) {
  591. display->DisplayMsg();
  592. return -1;
  593. }
  594. if (bgmap_name) {
  595. const char *mapset;
  596. bgMap = (struct Map_info *) G_malloc(sizeof (struct Map_info));
  597. mapset = G_find_vector2 (bgmap_name, "");
  598. Vect_open_old(bgMap, (char *) bgmap_name, (char *) mapset); /* TODO */
  599. }
  600. if (!ids.empty()) {
  601. list = Vect_new_list();
  602. for (std::vector<int>::const_iterator b = ids.begin(), e = ids.end();
  603. b != e; ++b) {
  604. Vect_list_append(list, *b);
  605. }
  606. }
  607. else {
  608. list = display->selected.ids;
  609. }
  610. nlines = Vect_get_num_lines(display->mapInfo);
  611. ret = Vedit_copy_lines (display->mapInfo, bgMap,
  612. list);
  613. if (ret > 0) {
  614. changeset = changesets.size();
  615. for (int line = nlines + 1; line <= Vect_get_num_lines(display->mapInfo); line++) {
  616. AddActionToChangeset(changeset, ADD, line);
  617. }
  618. }
  619. else {
  620. changesets.erase(changeset);
  621. }
  622. if (ret > 0 && bgMap && settings.breakLines) {
  623. for(int i = 1; i <= ret; i++)
  624. BreakLineAtIntersection(nlines + i, NULL, changeset);
  625. }
  626. if (list != display->selected.ids) {
  627. Vect_destroy_list(list);
  628. }
  629. if (bgMap) {
  630. Vect_close(bgMap);
  631. G_free ((void *) bgMap);
  632. }
  633. return ret;
  634. }
  635. /**
  636. \brief Open background vector map
  637. @todo support more background maps then only one
  638. \param bgmap pointer to vector map name
  639. \return vector map array
  640. \return NULL on error
  641. */
  642. struct Map_info** Digit::OpenBackgroundVectorMap(const char *bgmap)
  643. {
  644. char name[GNAME_MAX];
  645. char mapset[GMAPSET_MAX];
  646. int nbgmaps;
  647. struct Map_info** BgMap;
  648. if (!display->mapInfo) {
  649. return NULL;
  650. }
  651. if (G_find_vector2 (bgmap, "") == NULL) {
  652. return NULL;
  653. }
  654. nbgmaps = 0;
  655. BgMap = NULL;
  656. if (!G__name_is_fully_qualified(bgmap, name, mapset)) {
  657. strncpy(name, bgmap, GNAME_MAX);
  658. mapset[0] = '\0';
  659. }
  660. if (strcmp(G_fully_qualified_name((const char*) display->mapInfo->name, (const char*) G_mapset()),
  661. G_fully_qualified_name((const char*) bgmap, (const char*) mapset))) {
  662. nbgmaps = 1;
  663. BgMap = (struct Map_info**) G_malloc (nbgmaps * sizeof(struct Map_info*));
  664. BgMap[nbgmaps-1] = (struct Map_info *) G_malloc (sizeof(struct Map_info));
  665. // avoid GUI crash
  666. Vect_set_fatal_error(GV_FATAL_PRINT);
  667. if (Vect_open_old(BgMap[nbgmaps-1], name, mapset) == -1) {
  668. G_free ((void *) BgMap[nbgmaps-1]);
  669. BgMap = NULL;
  670. }
  671. }
  672. return BgMap;
  673. }
  674. /**
  675. \brief Type conversion of selected features
  676. Supported conversions:
  677. - point <-> centroid
  678. - line <-> boundary
  679. \return number of modified features
  680. \return -1 on error
  681. */
  682. int Digit::TypeConvLines()
  683. {
  684. int ret;
  685. int changeset, nlines;
  686. if (!display->mapInfo) {
  687. display->DisplayMsg();
  688. return -1;
  689. }
  690. nlines = Vect_get_num_lines(display->mapInfo);
  691. /* register changeset */
  692. changeset = AddActionsBefore();
  693. ret = Vedit_chtype_lines (display->mapInfo, display->selected.ids);
  694. if(ret > 0) {
  695. AddActionsAfter(changeset, nlines);
  696. }
  697. else {
  698. changesets.erase(changeset);
  699. }
  700. return ret;
  701. }
  702. /*!
  703. \brief Break given line at intersection
  704. \param line line id
  705. \return number of modified lines
  706. */
  707. int Digit::BreakLineAtIntersection(int line, struct line_pnts* points_line,
  708. int changeset)
  709. {
  710. int ret, type, nlines;
  711. int lineBreak;
  712. BOUND_BOX lineBox;
  713. struct ilist *list, *listBreak, *listRef;
  714. struct line_pnts *points_check, *points;
  715. if (!Vect_line_alive(display->mapInfo, line))
  716. return 0;
  717. if (!points_line) {
  718. points = Vect_new_line_struct();
  719. if (Vect_read_line(display->mapInfo, points, NULL, line) < 0) {
  720. display->ReadLineMsg(line);
  721. return -1;
  722. }
  723. }
  724. else {
  725. points = points_line;
  726. }
  727. list = Vect_new_list();
  728. listRef = Vect_new_list();
  729. listBreak = Vect_new_list();
  730. points_check = Vect_new_line_struct();
  731. /* find all relevant lines */
  732. Vect_get_line_box(display->mapInfo, line, &lineBox);
  733. Vect_select_lines_by_box(display->mapInfo, &lineBox,
  734. GV_LINES, list);
  735. /* check for intersection */
  736. Vect_list_append(listBreak, line);
  737. Vect_list_append(listRef, line);
  738. for (int i = 0; i < list->n_values; i++) {
  739. lineBreak = list->value[i];
  740. if (lineBreak == line)
  741. continue;
  742. type = Vect_read_line(display->mapInfo, points_check, NULL, lineBreak);
  743. if (!(type & GV_LINES))
  744. continue;
  745. if (Vect_line_check_intersection(points, points_check,
  746. WITHOUT_Z))
  747. Vect_list_append(listBreak, lineBreak);
  748. }
  749. nlines = Vect_get_num_lines(display->mapInfo);
  750. for (int i = 0; i < listBreak->n_values; i++) {
  751. AddActionToChangeset(changeset, DEL, listBreak->value[i]);
  752. }
  753. ret = Vect_break_lines_list(display->mapInfo, listBreak, listRef,
  754. GV_LINES, NULL);
  755. for (int i = 0; i < listBreak->n_values; i++) {
  756. if (Vect_line_alive(display->mapInfo, listBreak->value[i]))
  757. RemoveActionFromChangeset(changeset, DEL, listBreak->value[i]);
  758. }
  759. for (int line = nlines + 1; line <= Vect_get_num_lines(display->mapInfo); line++) {
  760. AddActionToChangeset(changeset, ADD, line);
  761. }
  762. Vect_destroy_line_struct(points_check);
  763. if (points != points_line)
  764. Vect_destroy_line_struct(points);
  765. Vect_destroy_list(list);
  766. Vect_destroy_list(listBreak);
  767. Vect_destroy_list(listRef);
  768. return ret;
  769. }