driver.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. /**
  2. \file driver.cpp
  3. \brief Experimental C++ wxWidgets display driver
  4. This driver is designed for wxPython GRASS GUI (digitization tool).
  5. Draw vector map layer to PseudoDC.
  6. (C) by the GRASS Development Team
  7. This program is free software under the GNU General Public
  8. License (>=v2). Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Martin Landa <landa.martin gmail.com>
  11. \date 2007-2008
  12. */
  13. #include <cmath>
  14. #include <clocale>
  15. #include "driver.h"
  16. /**
  17. \brief Initialize driver
  18. Allocate given structures.
  19. \param[in,out] PseudoDC device where to draw vector objects
  20. \return
  21. */
  22. DisplayDriver::DisplayDriver(void *device)
  23. {
  24. setlocale(LC_NUMERIC, "C");
  25. G_gisinit(""); /* GRASS functions */
  26. mapInfo = NULL;
  27. dc = (wxPseudoDC *) device;
  28. points = Vect_new_line_struct();
  29. pointsScreen = new wxList();
  30. cats = Vect_new_cats_struct();
  31. selected = Vect_new_list();
  32. selectedDupl = Vect_new_list();
  33. drawSegments = false;
  34. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  35. // Vect_set_fatal_error(GV_FATAL_PRINT);
  36. // G_set_error_routine(print_error);
  37. }
  38. /**
  39. \brief Destroy driver
  40. Close the map, deallocate given structures.
  41. \param
  42. \return
  43. */
  44. DisplayDriver::~DisplayDriver()
  45. {
  46. if (mapInfo)
  47. CloseMap();
  48. Vect_destroy_line_struct(points);
  49. delete pointsScreen;
  50. Vect_destroy_cats_struct(cats);
  51. Vect_destroy_list(selected);
  52. Vect_destroy_list(selectedDupl);
  53. }
  54. /**
  55. \brief Set device for drawing
  56. \param[in,out] PseudoDC device where to draw vector objects
  57. \return
  58. */
  59. void DisplayDriver::SetDevice(void *device)
  60. {
  61. dc = (wxPseudoDC *) device;
  62. return;
  63. }
  64. /**
  65. \brief Draw content of the vector map to device
  66. \return number of lines which were drawn
  67. \return -1 on error
  68. */
  69. int DisplayDriver::DrawMap(bool force)
  70. {
  71. if (!mapInfo || !dc)
  72. return -1;
  73. int nlines;
  74. BOUND_BOX mapBox;
  75. struct ilist *listLines;
  76. // ids.clear();
  77. listLines = Vect_new_list();
  78. ResetTopology();
  79. /* nlines = Vect_get_num_lines(mapInfo); */
  80. Vect_get_map_box(mapInfo, &mapBox);
  81. // draw lines inside of current display region
  82. nlines = Vect_select_lines_by_box(mapInfo, &(region.box),
  83. GV_POINTS | GV_LINES, // fixme
  84. listLines);
  85. G_debug(3, "wxDriver.DrawMap(): region: w=%f, e=%f, s=%f, n=%f",
  86. region.box.W, region.box.E, region.box.S, region.box.N);
  87. dc->BeginDrawing();
  88. for (int i = 0; i < listLines->n_values; i++) {
  89. DrawLine(listLines->value[i]);
  90. }
  91. dc->EndDrawing();
  92. // PrintIds();
  93. Vect_destroy_list(listLines);
  94. return listLines->n_values;
  95. }
  96. /**
  97. \brief Draw selected vector objects to the device
  98. \param[in] line id
  99. \return 1 on success
  100. \return -1 on failure (vector object is dead, etc.)
  101. */
  102. int DisplayDriver::DrawLine(int line)
  103. {
  104. if (!dc || !Vect_line_alive (mapInfo, line))
  105. return -1;
  106. int dcId; // 0 | 1 | segment id
  107. int type; // line type
  108. double x, y, z; // screen coordinates
  109. bool draw; // draw object ?
  110. wxPen *pen;
  111. pen = NULL;
  112. draw = false;
  113. // read line
  114. type = Vect_read_line (mapInfo, points, cats, line);
  115. // add ids
  116. // -> node1, line1, vertex1, line2, ..., node2
  117. // struct lineDesc desc = {points->n_points, dcId};
  118. // ids[line] = desc;
  119. // update id for next line
  120. // dcId += points->n_points * 2 - 1;
  121. if (IsSelected(line)) { // line selected ?
  122. if (settings.highlightDupl.enabled && IsDuplicated(line)) {
  123. pen = new wxPen(settings.highlightDupl.color, settings.lineWidth, wxSOLID);
  124. }
  125. else {
  126. pen = new wxPen(settings.highlight, settings.lineWidth, wxSOLID);
  127. }
  128. if (drawSelected) {
  129. draw = true;
  130. }
  131. else {
  132. draw = false;
  133. }
  134. dcId = 1;
  135. topology.highlight++;
  136. }
  137. else {
  138. dcId = 0;
  139. if (type & GV_LINES) {
  140. switch (type) {
  141. case GV_LINE:
  142. pen = new wxPen(settings.line.color, settings.lineWidth, wxSOLID);
  143. topology.line++;
  144. draw = settings.line.enabled;
  145. break;
  146. case GV_BOUNDARY:
  147. int left, right;
  148. Vect_get_line_areas(mapInfo, line,
  149. &left, &right);
  150. if (left == 0 && right == 0) {
  151. pen = new wxPen(settings.boundaryNo.color, settings.lineWidth, wxSOLID);
  152. topology.boundaryNo++;
  153. draw = settings.boundaryNo.enabled;
  154. }
  155. else if (left > 0 && right > 0) {
  156. pen = new wxPen(settings.boundaryTwo.color, settings.lineWidth, wxSOLID);
  157. topology.boundaryTwo++;
  158. draw = settings.boundaryTwo.enabled;
  159. }
  160. else {
  161. pen = new wxPen(settings.boundaryOne.color, settings.lineWidth, wxSOLID);
  162. topology.boundaryOne++;
  163. draw = settings.boundaryOne.enabled;
  164. }
  165. break;
  166. default:
  167. draw = false;
  168. break;
  169. }
  170. }
  171. else if (type & GV_POINTS) {
  172. if (type == GV_POINT && settings.point.enabled) {
  173. pen = new wxPen(settings.point.color, settings.lineWidth, wxSOLID);
  174. topology.point++;
  175. draw = settings.point.enabled;
  176. }
  177. else if (type == GV_CENTROID) {
  178. int cret = Vect_get_centroid_area(mapInfo, line);
  179. if (cret > 0) { // -> area
  180. draw = settings.centroidIn.enabled;
  181. pen = new wxPen(settings.centroidIn.color, settings.lineWidth, wxSOLID);
  182. topology.centroidIn++;
  183. }
  184. else if (cret == 0) {
  185. draw = settings.centroidOut.enabled;
  186. pen = new wxPen(settings.centroidOut.color, settings.lineWidth, wxSOLID);
  187. topology.centroidOut++;
  188. }
  189. else {
  190. draw = settings.centroidDup.enabled;
  191. pen = new wxPen(settings.centroidDup.color, settings.lineWidth, wxSOLID);
  192. topology.centroidDup++;
  193. }
  194. }
  195. }
  196. }
  197. // clear screen points & convert EN -> xy
  198. pointsScreen->Clear();
  199. for (int i = 0; i < points->n_points; i++) {
  200. Cell2Pixel(points->x[i], points->y[i], points->z[i],
  201. &x, &y, &z);
  202. pointsScreen->Append((wxObject*) new wxPoint((int) x, (int) y)); /* TODO: 3D */
  203. }
  204. dc->SetId(dcId); /* 0 | 1 (selected) */
  205. dc->SetPen(*pen);
  206. if (draw) {
  207. if (type & GV_POINTS) {
  208. DrawCross(line, (const wxPoint *) pointsScreen->GetFirst()->GetData());
  209. }
  210. else {
  211. // long int startId = ids[line].startId + 1;
  212. if (dcId > 0 && drawSegments) {
  213. dcId = 2; // first segment
  214. for (size_t i = 0; i < pointsScreen->GetCount() - 1; dcId += 2) {
  215. wxPoint *point_beg = (wxPoint *) pointsScreen->Item(i)->GetData();
  216. wxPoint *point_end = (wxPoint *) pointsScreen->Item(++i)->GetData();
  217. // set bounds for line
  218. // wxRect rect (*point_beg, *point_end);
  219. // dc->SetIdBounds(startId, rect);
  220. dc->SetId(dcId); // set unique id & set bbox for each segment
  221. dc->SetPen(*pen);
  222. wxRect rect (*point_beg, *point_end);
  223. dc->SetIdBounds(dcId, rect);
  224. dc->DrawLine(point_beg->x, point_beg->y,
  225. point_end->x, point_end->y);
  226. }
  227. }
  228. else {
  229. wxPoint wxPoints[pointsScreen->GetCount()];
  230. for (size_t i = 0; i < pointsScreen->GetCount(); i++) {
  231. wxPoint *point_beg = (wxPoint *) pointsScreen->Item(i)->GetData();
  232. wxPoints[i] = *point_beg;
  233. }
  234. dc->DrawLines(pointsScreen->GetCount(), wxPoints);
  235. if (!IsSelected(line) && settings.direction.enabled) {
  236. DrawDirectionArrow();
  237. // restore pen
  238. dc->SetPen(*pen);
  239. }
  240. }
  241. }
  242. }
  243. if (type & GV_LINES) {
  244. DrawLineVerteces(line); // draw vertices
  245. DrawLineNodes(line); // draw nodes
  246. }
  247. delete pen;
  248. return 1;
  249. }
  250. /**
  251. \brief Draw line verteces to the device
  252. Except of first and last vertex, see DrawLineNodes().
  253. \param line id
  254. \return number of verteces which were drawn
  255. \return -1 if drawing vertices is disabled
  256. */
  257. int DisplayDriver::DrawLineVerteces(int line)
  258. {
  259. int dcId;
  260. wxPoint *point;
  261. wxPen *pen;
  262. if (!IsSelected(line) && !settings.vertex.enabled)
  263. return -1;
  264. // determine color
  265. if (!IsSelected(line)) {
  266. pen = new wxPen(settings.vertex.color, settings.lineWidth, wxSOLID);
  267. dcId = 0;
  268. }
  269. else {
  270. if (!drawSelected) {
  271. return -1;
  272. }
  273. if (settings.highlightDupl.enabled && IsDuplicated(line)) {
  274. pen = new wxPen(settings.highlightDupl.color, settings.lineWidth, wxSOLID);
  275. }
  276. else {
  277. pen = new wxPen(settings.highlight, settings.lineWidth, wxSOLID);
  278. }
  279. if (drawSegments) {
  280. dcId = 3; // first vertex
  281. }
  282. else {
  283. dcId = 1;
  284. }
  285. }
  286. dc->SetId(dcId); /* 0 | 1 (selected) */
  287. dc->SetPen(*pen);
  288. for (size_t i = 1; i < pointsScreen->GetCount() - 1; i++, dcId += 2) {
  289. point = (wxPoint*) pointsScreen->Item(i)->GetData();
  290. if (IsSelected(line) && drawSegments) {
  291. dc->SetId(dcId);
  292. dc->SetPen(*pen);
  293. wxRect rect (*point, *point);
  294. dc->SetIdBounds(dcId, rect);
  295. }
  296. if (settings.vertex.enabled) {
  297. DrawCross(line, (const wxPoint*) pointsScreen->Item(i)->GetData());
  298. topology.vertex++;
  299. }
  300. }
  301. delete pen;
  302. return pointsScreen->GetCount() - 2;
  303. }
  304. /**
  305. \brief Draw line nodes to the device
  306. \param line id
  307. \return 1
  308. \return -1 if no nodes were drawn
  309. */
  310. int DisplayDriver::DrawLineNodes(int line)
  311. {
  312. int dcId;
  313. int node;
  314. double east, north, depth;
  315. double x, y, z;
  316. int nodes [2];
  317. bool draw;
  318. wxPen *pen;
  319. // draw nodes??
  320. if (!settings.nodeOne.enabled && !settings.nodeTwo.enabled)
  321. return -1;
  322. // get nodes
  323. Vect_get_line_nodes(mapInfo, line, &(nodes[0]), &(nodes[1]));
  324. for (size_t i = 0; i < sizeof(nodes) / sizeof(int); i++) {
  325. node = nodes[i];
  326. // get coordinates
  327. Vect_get_node_coor(mapInfo, node,
  328. &east, &north, &depth);
  329. // convert EN->xy
  330. Cell2Pixel(east, north, depth,
  331. &x, &y, &z);
  332. // determine color
  333. if (IsSelected(line)) {
  334. if (!drawSelected) {
  335. return -1;
  336. }
  337. if (settings.highlightDupl.enabled && IsDuplicated(line)) {
  338. pen = new wxPen(settings.highlightDupl.color, settings.lineWidth, wxSOLID);
  339. }
  340. else {
  341. pen = new wxPen(settings.highlight, settings.lineWidth, wxSOLID);
  342. }
  343. draw = true;
  344. if (!drawSegments) {
  345. dcId = 1;
  346. }
  347. else {
  348. // node1, line1, vertex1, line2, vertex2, ..., node2
  349. if (i == 0) // first node
  350. dcId = 1;
  351. else // last node
  352. dcId = 2 * points->n_points - 1;
  353. }
  354. }
  355. else {
  356. dcId = 0;
  357. if (Vect_get_node_n_lines(mapInfo, node) == 1) {
  358. pen = new wxPen(settings.nodeOne.color, settings.lineWidth, wxSOLID);
  359. topology.nodeOne++;
  360. draw = settings.nodeOne.enabled;
  361. }
  362. else {
  363. pen = new wxPen(settings.nodeTwo.color, settings.lineWidth, wxSOLID);
  364. topology.nodeTwo++;
  365. draw = settings.nodeTwo.enabled;
  366. }
  367. }
  368. wxPoint point((int) x, (int) y);
  369. if (IsSelected(line) && drawSegments) {
  370. wxRect rect (point, point);
  371. dc->SetIdBounds(dcId, rect);
  372. }
  373. // draw node if needed
  374. if (draw) {
  375. dc->SetId(dcId);
  376. dc->SetPen(*pen);
  377. DrawCross(line, &point);
  378. }
  379. }
  380. delete pen;
  381. return 1;
  382. }
  383. /*
  384. \brief Close vector map layer
  385. \param void
  386. \return 0 on success
  387. \return non-zero on error
  388. */
  389. int DisplayDriver::CloseMap()
  390. {
  391. int ret;
  392. ret = -1;
  393. if (mapInfo) {
  394. if (mapInfo->mode == GV_MODE_RW) {
  395. /* rebuild topology */
  396. Vect_build_partial(mapInfo, GV_BUILD_NONE, NULL);
  397. Vect_build(mapInfo, NULL);
  398. }
  399. /* close map and store topo/cidx */
  400. ret = Vect_close(mapInfo);
  401. G_free ((void *) mapInfo);
  402. mapInfo = NULL;
  403. }
  404. return ret;
  405. }
  406. /**
  407. \brief Open vector map layer
  408. \param[in] mapname name of vector map
  409. \param[in] mapset name of mapset where the vector map layer is stored
  410. \return topo level
  411. \return -1 on error
  412. */
  413. int DisplayDriver::OpenMap(const char* mapname, const char *mapset, bool update)
  414. {
  415. int ret;
  416. if (!mapInfo)
  417. mapInfo = (struct Map_info *) G_malloc (sizeof (struct Map_info));
  418. // define open level (level 2: topology)
  419. Vect_set_open_level(2);
  420. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  421. Vect_set_fatal_error(GV_FATAL_PRINT);
  422. // open existing map
  423. if (!update) {
  424. ret = Vect_open_old(mapInfo, (char*) mapname, (char *) mapset);
  425. }
  426. else {
  427. ret = Vect_open_update(mapInfo, (char*) mapname, (char *) mapset);
  428. }
  429. if (ret == -1) { // error
  430. G_free((void *) mapInfo);
  431. mapInfo = NULL;
  432. }
  433. return ret;
  434. }
  435. /**
  436. \brief Reload vector map layer
  437. Close and open again. Needed for modification using v.edit.
  438. TODO: Get rid of that...
  439. \param
  440. \return
  441. */
  442. void DisplayDriver::ReloadMap()
  443. {
  444. // char* name = G_store(Vect_get_map_name(mapInfo)); ???
  445. char* name = G_store(mapInfo->name);
  446. char* mapset = G_store(Vect_get_mapset(mapInfo));
  447. Vect_close(mapInfo);
  448. mapInfo = NULL;
  449. OpenMap(name, mapset, false); // used only for v.edit
  450. //Vect_build_partial(mapInfo, GV_BUILD_NONE, stderr);
  451. //Vect_build(mapInfo, stderr);
  452. return;
  453. }
  454. /*
  455. \brief Conversion from geographic coordinates (east, north)
  456. to screen (x, y)
  457. TODO: 3D stuff...
  458. \param[in] east,north,depth geographical coordinates
  459. \param[out] x, y, z screen coordinates
  460. \return
  461. */
  462. void DisplayDriver::Cell2Pixel(double east, double north, double depth,
  463. double *x, double *y, double *z)
  464. {
  465. double n, w;
  466. /*
  467. *x = int((east - region.map_west) / region.map_res);
  468. *y = int((region.map_north - north) / region.map_res);
  469. */
  470. w = region.center_easting - (region.map_width / 2) * region.map_res;
  471. n = region.center_northing + (region.map_height / 2) * region.map_res;
  472. /*
  473. *x = int((east - w) / region.map_res);
  474. *y = int((n - north) / region.map_res);
  475. */
  476. if (x)
  477. *x = (east - w) / region.map_res;
  478. if (y)
  479. *y = (n - north) / region.map_res;
  480. if (z)
  481. *z = 0.;
  482. return;
  483. }
  484. /**
  485. \brief Calculate distance in pixels
  486. \todo LL projection
  487. \param dist real distance
  488. */
  489. double DisplayDriver::DistanceInPixels(double dist)
  490. {
  491. double x;
  492. Cell2Pixel(region.map_west + dist, region.map_north, 0.0, &x, NULL, NULL);
  493. return std::sqrt(x * x);
  494. }
  495. /**
  496. \brief Set geographical region
  497. Region must be upgraded because of Cell2Pixel().
  498. \param[in] north,south,east,west,ns_res,ew_res region settings
  499. \return
  500. */
  501. void DisplayDriver::SetRegion(double north, double south, double east, double west,
  502. double ns_res, double ew_res,
  503. double center_easting, double center_northing,
  504. double map_width, double map_height)
  505. {
  506. region.box.N = north;
  507. region.box.S = south;
  508. region.box.E = east;
  509. region.box.W = west;
  510. region.box.T = PORT_DOUBLE_MAX;
  511. region.box.B = -PORT_DOUBLE_MAX;
  512. region.ns_res = ns_res;
  513. region.ew_res = ew_res;
  514. region.center_easting = center_easting;
  515. region.center_northing = center_northing;
  516. region.map_width = map_width;
  517. region.map_height = map_height;
  518. // calculate real region
  519. region.map_res = (region.ew_res > region.ns_res) ? region.ew_res : region.ns_res;
  520. region.map_west = region.center_easting - (region.map_width / 2.) * region.map_res;
  521. region.map_north = region.center_northing + (region.map_height / 2.) * region.map_res;
  522. return;
  523. }
  524. /**
  525. \brief Draw cross symbol of given size to device content
  526. Used for points, nodes, vertices
  527. \param[in] point coordinates of center
  528. \param[in] size size of the cross symbol
  529. \return 1 on success
  530. \return -1 on failure
  531. */
  532. int DisplayDriver::DrawCross(int line, const wxPoint* point, int size)
  533. {
  534. if (!dc || !point)
  535. return -1;
  536. dc->DrawLine(point->x - size, point->y, point->x + size, point->y);
  537. dc->DrawLine(point->x, point->y - size, point->x, point->y + size);
  538. return 1;
  539. }
  540. /*
  541. \brief Set settings for displaying vector feature
  542. E.g. line width, color, ...
  543. \param[in] lineWidth,... settgings
  544. \return
  545. */
  546. void DisplayDriver::UpdateSettings(unsigned long highlight,
  547. bool ehighlightDupl, unsigned long chighlightDupl,
  548. bool ePoint, unsigned long cPoint, /* enabled, color */
  549. bool eLine, unsigned long cLine,
  550. bool eBoundaryNo, unsigned long cBoundaryNo,
  551. bool eBoundaryOne, unsigned long cBoundaryOne,
  552. bool eBoundaryTwo, unsigned long cBoundaryTwo,
  553. bool eCentroidIn, unsigned long cCentroidIn,
  554. bool eCentroidOut, unsigned long cCentroidOut,
  555. bool eCentroidDup, unsigned long cCentroidDup,
  556. bool eNodeOne, unsigned long cNodeOne,
  557. bool eNodeTwo, unsigned long cNodeTwo,
  558. bool eVertex, unsigned long cVertex,
  559. bool eDirection, unsigned long cDirection,
  560. int lineWidth)
  561. {
  562. settings.highlight.Set(highlight);
  563. settings.highlightDupl.enabled = ehighlightDupl;
  564. settings.highlightDupl.color.Set(chighlightDupl);
  565. settings.point.enabled = ePoint;
  566. settings.point.color.Set(cPoint);
  567. settings.line.enabled = eLine;
  568. settings.line.color.Set(cLine);
  569. settings.boundaryNo.enabled = eBoundaryNo;
  570. settings.boundaryNo.color.Set(cBoundaryNo);
  571. settings.boundaryOne.enabled = eBoundaryOne;
  572. settings.boundaryOne.color.Set(cBoundaryOne);
  573. settings.boundaryTwo.enabled = eBoundaryTwo;
  574. settings.boundaryTwo.color.Set(cBoundaryTwo);
  575. settings.centroidIn.enabled = eCentroidIn;
  576. settings.centroidIn.color.Set(cCentroidIn);
  577. settings.centroidOut.enabled = eCentroidOut;
  578. settings.centroidOut.color.Set(cCentroidOut);
  579. settings.centroidDup.enabled = eCentroidDup;
  580. settings.centroidDup.color.Set(cCentroidDup);
  581. settings.nodeOne.enabled = eNodeOne;
  582. settings.nodeOne.color.Set(cNodeOne);
  583. settings.nodeTwo.enabled = eNodeTwo;
  584. settings.nodeTwo.color.Set(cNodeTwo);
  585. settings.vertex.enabled = eVertex;
  586. settings.vertex.color.Set(cVertex);
  587. settings.direction.enabled = eDirection;
  588. settings.direction.color.Set(cDirection);
  589. settings.lineWidth = lineWidth;
  590. }
  591. /**
  592. \brief Prints gId: dcIds
  593. Useful for debugging purposes.
  594. \param
  595. \return
  596. */
  597. void DisplayDriver::PrintIds()
  598. {
  599. std::cerr << "topology.highlight: " << topology.highlight << std::endl;
  600. std::cerr << "topology.point: " << topology.point << std::endl;
  601. std::cerr << "topology.line: " << topology.line << std::endl;
  602. std::cerr << "topology.boundaryNo: " << topology.boundaryNo << std::endl;
  603. std::cerr << "topology.boundaryOne: " << topology.boundaryOne << std::endl;
  604. std::cerr << "topology.boundaryTwo: " << topology.boundaryTwo << std::endl;
  605. std::cerr << "topology.centroidIn: " << topology.centroidIn << std::endl;
  606. std::cerr << "topology.centroidOut: " << topology.centroidOut << std::endl;
  607. std::cerr << "topology.centroidDup: " << topology.centroidDup << std::endl;
  608. std::cerr << "topology.nodeOne: " << topology.nodeOne << std::endl;
  609. std::cerr << "topology.nodeTwo: " << topology.nodeTwo << std::endl;
  610. std::cerr << "topology.vertex: " << topology.vertex << std::endl;
  611. std::cerr << std::endl << "nobjects: "
  612. << topology.point * 2 + // cross
  613. topology.line +
  614. topology.boundaryNo +
  615. topology.boundaryOne +
  616. topology.boundaryTwo +
  617. topology.centroidIn * 2 +
  618. topology.centroidOut * 2 +
  619. topology.centroidDup * 2 +
  620. topology.nodeOne * 2 +
  621. topology.nodeTwo * 2 +
  622. topology.vertex * 2 << std::endl;
  623. std::cerr << "selected: ";
  624. for (int i = 0; i < selected->n_values; i++) {
  625. std::cerr << selected->value[i] << " ";
  626. }
  627. std::cerr << std::endl;
  628. return;
  629. }
  630. /**
  631. \brief Select vector objects by given bounding box
  632. If line id is already in the list of selected lines, then it will
  633. be excluded from this list.
  634. \param[in] x1,y1,z1,x2,y2,z3 bounding box definition
  635. \param[in] type feature type
  636. \return number of selected features
  637. \return -1 on error
  638. */
  639. int DisplayDriver::SelectLinesByBox(double x1, double y1, double z1,
  640. double x2, double y2, double z2,
  641. int type)
  642. {
  643. if (!mapInfo)
  644. return -1;
  645. int line;
  646. struct ilist *list;
  647. struct line_pnts *bbox;
  648. drawSegments = false;
  649. drawSelected = true;
  650. list = Vect_new_list();
  651. bbox = Vect_new_line_struct();
  652. Vect_append_point(bbox, x1, y1, z1);
  653. Vect_append_point(bbox, x2, y1, z2);
  654. Vect_append_point(bbox, x2, y2, z1);
  655. Vect_append_point(bbox, x1, y2, z2);
  656. Vect_append_point(bbox, x1, y1, z1);
  657. Vect_select_lines_by_polygon(mapInfo, bbox,
  658. 0, NULL, /* isles */
  659. type, list);
  660. for (int i = 0; i < list->n_values; i++) {
  661. line = list->value[i];
  662. if (!IsSelected(line)) {
  663. Vect_list_append(selected, line);
  664. }
  665. else {
  666. Vect_list_delete(selected, line);
  667. }
  668. }
  669. Vect_destroy_line_struct(bbox);
  670. Vect_destroy_list(list);
  671. return list->n_values;
  672. }
  673. /**
  674. \brief Select vector feature by given point in given
  675. threshold
  676. Only one vector object can be selected. Bounding boxes of
  677. all segments are stores.
  678. \param[in] x,y point of searching
  679. \param[in] thresh threshold value where to search
  680. \param[in] type select vector object of given type
  681. \return point on line if line found
  682. */
  683. std::vector<double> DisplayDriver::SelectLineByPoint(double x, double y, double z,
  684. double thresh, int type, int with_z)
  685. {
  686. long int line;
  687. double px, py, pz;
  688. std::vector<double> p;
  689. drawSelected = true;
  690. line = Vect_find_line(mapInfo, x, y, z,
  691. type, thresh, with_z, 0);
  692. if (line > 0) {
  693. if (!IsSelected(line)) {
  694. Vect_list_append(selected, line);
  695. }
  696. else {
  697. Vect_list_delete(selected, line);
  698. }
  699. type = Vect_read_line (mapInfo, points, cats, line);
  700. Vect_line_distance (points, x, y, z, with_z,
  701. &px, &py, &pz,
  702. NULL, NULL, NULL);
  703. p.push_back(px);
  704. p.push_back(py);
  705. if (with_z) {
  706. p.push_back(pz);
  707. }
  708. }
  709. drawSegments = true;
  710. return p;
  711. }
  712. /**
  713. \brief Is vector object selected?
  714. \param[in] line id
  715. \return true if vector object is selected
  716. \return false if vector object is not selected
  717. */
  718. bool DisplayDriver::IsSelected(int line)
  719. {
  720. if (Vect_val_in_list(selected, line))
  721. return true;
  722. return false;
  723. }
  724. /**
  725. \brief Get ids of selected objects
  726. \param[in] grassId if true return GRASS line ids
  727. if false return PseudoDC ids
  728. \return list of ids of selected vector objects
  729. */
  730. std::vector<int> DisplayDriver::GetSelected(bool grassId)
  731. {
  732. if (grassId)
  733. return ListToVector(selected);
  734. std::vector<int> dc_ids;
  735. if (!drawSegments) {
  736. dc_ids.push_back(1);
  737. }
  738. else {
  739. int npoints;
  740. Vect_read_line(mapInfo, points, NULL, selected->value[0]);
  741. npoints = points->n_points;
  742. for (int i = 1; i < 2 * npoints; i++) {
  743. dc_ids.push_back(i);
  744. }
  745. }
  746. return dc_ids;
  747. }
  748. /**
  749. \brief Get feature (grass) ids of duplicated objects
  750. \return list of ids
  751. */
  752. std::map<int, std::vector <int> > DisplayDriver::GetDuplicates()
  753. {
  754. std::map<int, std::vector<int> > ids;
  755. struct line_pnts *APoints, *BPoints;
  756. int line;
  757. APoints = Vect_new_line_struct();
  758. BPoints = Vect_new_line_struct();
  759. Vect_reset_list(selectedDupl);
  760. for (int i = 0; i < selected->n_values; i++) {
  761. line = selected->value[i];
  762. if (IsDuplicated(line))
  763. continue;
  764. Vect_read_line(mapInfo, APoints, NULL, line);
  765. for (int j = 0; j < selected->n_values; j++) {
  766. if (i == j || IsDuplicated(selected->value[j]))
  767. continue;
  768. Vect_read_line(mapInfo, BPoints, NULL, selected->value[j]);
  769. if (Vect_line_check_duplicate (APoints, BPoints, WITHOUT_Z)) {
  770. if (ids.find(i) == ids.end()) {
  771. ids[i] = std::vector<int> ();
  772. ids[i].push_back(selected->value[i]);
  773. Vect_list_append(selectedDupl, selected->value[i]);
  774. }
  775. ids[i].push_back(selected->value[j]);
  776. Vect_list_append(selectedDupl, selected->value[j]);
  777. }
  778. }
  779. }
  780. Vect_destroy_line_struct(APoints);
  781. Vect_destroy_line_struct(BPoints);
  782. return ids;
  783. }
  784. /**
  785. \brief Check for already marked duplicates
  786. \param line line id
  787. \return 1 line already marked as duplicated
  788. \return 0 not duplicated
  789. */
  790. bool DisplayDriver::IsDuplicated(int line)
  791. {
  792. if (Vect_val_in_list(selectedDupl, line))
  793. return true;
  794. return false;
  795. }
  796. /**
  797. \brief Set selected vector objects
  798. \param[in] list of GRASS ids to be set
  799. \return 1
  800. */
  801. int DisplayDriver::SetSelected(std::vector<int> id)
  802. {
  803. drawSelected = true;
  804. VectorToList(selected, id);
  805. if (selected->n_values <= 0)
  806. drawSegments = false;
  807. return 1;
  808. }
  809. /**
  810. \brief Unselect selected vector features
  811. \param[in] list of GRASS feature ids
  812. \return number of selected features
  813. */
  814. int DisplayDriver::UnSelect(std::vector<int> id)
  815. {
  816. bool checkForDupl;
  817. checkForDupl = false;
  818. for (std::vector<int>::const_iterator i = id.begin(), e = id.end();
  819. i != e; ++i) {
  820. if (IsSelected(*i)) {
  821. Vect_list_delete(selected, *i);
  822. }
  823. if (settings.highlightDupl.enabled && IsDuplicated(*i)) {
  824. checkForDupl = true;
  825. }
  826. }
  827. if (checkForDupl) {
  828. GetDuplicates();
  829. }
  830. return selected->n_values;
  831. }
  832. /**
  833. \brief Get PseudoDC vertex id of selected line
  834. Set bounding box for vertices of line.
  835. \param[in] x,y coordinates of click
  836. \param[in] thresh threshold value
  837. \return id of center, left and right vertex
  838. \return 0 no line found
  839. \return -1 on error
  840. */
  841. std::vector<int> DisplayDriver::GetSelectedVertex(double x, double y, double thresh)
  842. {
  843. int startId;
  844. int line, type;
  845. int Gid, DCid;
  846. double vx, vy, vz; // vertex screen coordinates
  847. double dist, minDist;
  848. std::vector<int> returnId;
  849. // only one object can be selected
  850. if (selected->n_values != 1 || !drawSegments)
  851. return returnId;
  852. startId = 1;
  853. line = selected->value[0];
  854. type = Vect_read_line (mapInfo, points, cats, line);
  855. minDist = 0.0;
  856. Gid = -1;
  857. // find the closest vertex (x, y)
  858. DCid = 1;
  859. for(int idx = 0; idx < points->n_points; idx++) {
  860. dist = Vect_points_distance(x, y, 0.0,
  861. points->x[idx], points->y[idx], points->z[idx], 0);
  862. if (idx == 0) {
  863. minDist = dist;
  864. Gid = idx;
  865. }
  866. else {
  867. if (minDist > dist) {
  868. minDist = dist;
  869. Gid = idx;
  870. }
  871. }
  872. Cell2Pixel(points->x[idx], points->y[idx], points->z[idx],
  873. &vx, &vy, &vz);
  874. wxRect rect (wxPoint ((int) vx, (int) vy), wxPoint ((int) vx, (int) vy));
  875. dc->SetIdBounds(DCid, rect);
  876. DCid+=2;
  877. }
  878. if (minDist > thresh)
  879. return returnId;
  880. // desc = &(ids[line]);
  881. // translate id
  882. DCid = Gid * 2 + 1;
  883. // add selected vertex
  884. returnId.push_back(DCid);
  885. // left vertex
  886. if (DCid == startId) {
  887. returnId.push_back(-1);
  888. }
  889. else {
  890. returnId.push_back(DCid - 2);
  891. }
  892. // right vertex
  893. if (DCid == (points->n_points - 1) * 2 + startId) {
  894. returnId.push_back(-1);
  895. }
  896. else {
  897. returnId.push_back(DCid + 2);
  898. }
  899. return returnId;
  900. }
  901. /**
  902. \brief Reset topology structure.
  903. \return
  904. */
  905. void DisplayDriver::ResetTopology()
  906. {
  907. topology.highlight = 0;
  908. topology.point = 0;
  909. topology.line = 0;
  910. topology.boundaryNo = 0;
  911. topology.boundaryOne = 0;
  912. topology.boundaryTwo = 0;
  913. topology.centroidIn = 0;
  914. topology.centroidOut = 0;
  915. topology.centroidDup = 0;
  916. topology.nodeOne = 0;
  917. topology.nodeTwo = 0;
  918. topology.vertex = 0;
  919. return;
  920. }
  921. /**
  922. \brief Convert vect list to std::vector
  923. \param list vect list
  924. \return std::vector
  925. */
  926. std::vector<int> DisplayDriver::ListToVector(struct ilist *list)
  927. {
  928. std::vector<int> vect;
  929. if (!list)
  930. return vect;
  931. for (int i = 0; i < list->n_values; i++) {
  932. vect.push_back(list->value[i]);
  933. }
  934. return vect;
  935. }
  936. /**
  937. \brief Convert std::vector to vect list
  938. \param list vect list
  939. \param vec std::vector instance
  940. \return number of items
  941. \return -1 on error
  942. */
  943. int DisplayDriver::VectorToList(struct ilist *list, const std::vector<int>& vec)
  944. {
  945. if (!list)
  946. return -1;
  947. Vect_reset_list(list);
  948. for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end();
  949. i != e; ++i) {
  950. Vect_list_append(list, *i);
  951. }
  952. return list->n_values;
  953. }
  954. /**
  955. \brief Get bounding box of (opened) vector map layer
  956. \return (w,s,b,e,n,t)
  957. */
  958. std::vector<double> DisplayDriver::GetMapBoundingBox()
  959. {
  960. std::vector<double> region;
  961. BOUND_BOX bbox;
  962. if (!mapInfo) {
  963. return region;
  964. }
  965. Vect_get_map_box(mapInfo, &bbox);
  966. region.push_back(bbox.W);
  967. region.push_back(bbox.S);
  968. region.push_back(bbox.B);
  969. region.push_back(bbox.E);
  970. region.push_back(bbox.N);
  971. region.push_back(bbox.T);
  972. return region;
  973. }
  974. /**
  975. \brief Error messages handling
  976. \param msg message
  977. \param type type message (MSG, WARN, ERR)
  978. \return 0
  979. */
  980. int print_error(const char *msg, int type)
  981. {
  982. fprintf(stderr, "%s", msg);
  983. return 0;
  984. }
  985. /**
  986. \brief Draw selected features
  987. \param draw if true draw selected features
  988. */
  989. void DisplayDriver::DrawSelected(bool draw)
  990. {
  991. drawSelected = draw;
  992. return;
  993. }
  994. /**
  995. \brief Draw line direction arrow
  996. \return number of drawn arrows
  997. */
  998. int DisplayDriver::DrawDirectionArrow()
  999. {
  1000. int narrows;
  1001. int size; // arrow length in pixels
  1002. int limit; // segment length limit for drawing symbol (in pixels)
  1003. double dist, angle, pos;
  1004. double e, n, d, x0, y0, z0, x1, y1, z1;
  1005. struct line_pnts *points_seg;
  1006. wxPen *pen_arrow;
  1007. narrows = 0;
  1008. size = 5;
  1009. limit = 5; // 5px for line segment
  1010. points_seg = Vect_new_line_struct();
  1011. pen_arrow = new wxPen(settings.direction.color, settings.lineWidth, wxSOLID);
  1012. dc->SetPen(*pen_arrow);
  1013. dist = Vect_line_length(points);
  1014. if (DistanceInPixels(dist) >= limit) {
  1015. while (1) {
  1016. pos = (narrows + 1) * 8 * limit * region.map_res;
  1017. if (Vect_point_on_line(points, pos,
  1018. &e, &n, &d, NULL, NULL) < 1) {
  1019. break;
  1020. }
  1021. Cell2Pixel(e, n, d, &x0, &y0, &z0);
  1022. if (Vect_point_on_line(points, pos - 3 * size * region.map_res,
  1023. &e, &n, &d, &angle, NULL) < 1) {
  1024. break;
  1025. }
  1026. Cell2Pixel(e, n, d, &x1, &y1, &z1);
  1027. DrawArrow(x0, y0, x1, y1, angle, size);
  1028. if(narrows > 1e2) // low resolution, break
  1029. break;
  1030. narrows++;
  1031. }
  1032. // draw at least one arrow in the middle of line
  1033. if (narrows < 1) {
  1034. dist /= 2.;
  1035. if (Vect_point_on_line(points, dist,
  1036. &e, &n, &d, NULL, NULL) > 0) {
  1037. Cell2Pixel(e, n, d, &x0, &y0, &z0);
  1038. if (Vect_point_on_line(points, dist - 3 * size * region.map_res,
  1039. &e, &n, &d, &angle, NULL) > 0) {
  1040. Cell2Pixel(e, n, d, &x1, &y1, &z1);
  1041. DrawArrow(x0, y0, x1, y1, angle, size);
  1042. }
  1043. }
  1044. }
  1045. }
  1046. Vect_destroy_line_struct(points_seg);
  1047. return narrows;
  1048. }
  1049. /**
  1050. \brief Draw arrow symbol on line
  1051. \param x0,y0 arrow origin
  1052. \param x1,x1 arrow ending point (on line)
  1053. \param angle point ending point angle
  1054. \param size arrow size
  1055. \return 1
  1056. */
  1057. int DisplayDriver::DrawArrow(double x0, double y0,
  1058. double x1, double y1, double angle,
  1059. int size)
  1060. {
  1061. double x, y;
  1062. double angle_symb;
  1063. angle_symb = angle - M_PI / 2.;
  1064. x = x1 + size * std::cos(angle_symb);
  1065. y = y1 - size * std::sin(angle_symb);
  1066. dc->DrawLine((wxCoord) x, (wxCoord) y, (wxCoord) x0, (wxCoord) y0);
  1067. angle_symb = M_PI / 2. + angle;
  1068. x = x1 + size * std::cos(angle_symb);
  1069. y = y1 - size * std::sin(angle_symb);
  1070. dc->DrawLine((wxCoord) x0, (wxCoord) y0, (wxCoord) x, (wxCoord) y);
  1071. return 1;
  1072. }