driver.cpp 26 KB

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