driver.cpp 27 KB

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