line.cpp 22 KB

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