driver.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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 "driver.h"
  15. /**
  16. \brief Initialize driver
  17. Allocate given structures.
  18. \param[in,out] PseudoDC device where to draw vector objects
  19. \param[in,out] PseudoDC device where to draw vector objects (tmp, selected)
  20. \return
  21. */
  22. DisplayDriver::DisplayDriver(void *device, void *deviceTmp)
  23. {
  24. G_gisinit(""); /* GRASS functions */
  25. mapInfo = NULL;
  26. dc = (wxPseudoDC *) device;
  27. dcTmp = (wxPseudoDC *) deviceTmp;
  28. points = Vect_new_line_struct();
  29. pointsScreen = new wxList();
  30. cats = Vect_new_cats_struct();
  31. selected.field = -1;
  32. selected.cats = Vect_new_list();
  33. selected.ids = Vect_new_list();
  34. selected.idsDupl = Vect_new_list();
  35. drawSegments = false;
  36. G_set_verbose(0);
  37. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  38. // Vect_set_fatal_error(GV_FATAL_PRINT);
  39. // G_set_error_routine(print_error);
  40. }
  41. /**
  42. \brief Destroy driver
  43. Close the map, deallocate given structures.
  44. \param
  45. \return
  46. */
  47. DisplayDriver::~DisplayDriver()
  48. {
  49. if (mapInfo)
  50. CloseMap();
  51. Vect_destroy_line_struct(points);
  52. delete pointsScreen;
  53. Vect_destroy_cats_struct(cats);
  54. Vect_destroy_list(selected.cats);
  55. Vect_destroy_list(selected.ids);
  56. Vect_destroy_list(selected.idsDupl);
  57. }
  58. /**
  59. \brief Set device for drawing
  60. \param[in,out] PseudoDC device where to draw vector objects
  61. \return
  62. */
  63. void DisplayDriver::SetDevice(void *device)
  64. {
  65. dc = (wxPseudoDC *) device;
  66. return;
  67. }
  68. /*
  69. \brief Close vector map layer
  70. \param void
  71. \return 0 on success
  72. \return non-zero on error
  73. */
  74. int DisplayDriver::CloseMap()
  75. {
  76. int ret;
  77. ret = -1;
  78. if (mapInfo) {
  79. if (mapInfo->mode == GV_MODE_RW) {
  80. /* rebuild topology */
  81. Vect_build_partial(mapInfo, GV_BUILD_NONE);
  82. Vect_build(mapInfo);
  83. }
  84. /* close map and store topo/cidx */
  85. ret = Vect_close(mapInfo);
  86. G_free ((void *) mapInfo);
  87. mapInfo = NULL;
  88. }
  89. return ret;
  90. }
  91. /**
  92. \brief Open vector map layer
  93. \param[in] mapname name of vector map
  94. \param[in] mapset name of mapset where the vector map layer is stored
  95. \return topo level
  96. \return -1 on error
  97. */
  98. int DisplayDriver::OpenMap(const char* mapname, const char *mapset, bool update)
  99. {
  100. int ret;
  101. if (!mapInfo)
  102. mapInfo = (struct Map_info *) G_malloc (sizeof (struct Map_info));
  103. // define open level (level 2: topology)
  104. Vect_set_open_level(2);
  105. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  106. Vect_set_fatal_error(GV_FATAL_PRINT);
  107. // open existing map
  108. if (!update) {
  109. ret = Vect_open_old(mapInfo, (char*) mapname, (char *) mapset);
  110. }
  111. else {
  112. ret = Vect_open_update(mapInfo, (char*) mapname, (char *) mapset);
  113. }
  114. if (ret == -1) { // error
  115. G_free((void *) mapInfo);
  116. mapInfo = NULL;
  117. }
  118. return ret;
  119. }
  120. /**
  121. \brief Reload vector map layer
  122. Close and open again. Needed for modification using v.edit.
  123. TODO: Get rid of that...
  124. \param
  125. \return
  126. */
  127. void DisplayDriver::ReloadMap()
  128. {
  129. // char* name = G_store(Vect_get_map_name(mapInfo)); ???
  130. char* name = G_store(mapInfo->name);
  131. char* mapset = G_store(Vect_get_mapset(mapInfo));
  132. Vect_close(mapInfo);
  133. mapInfo = NULL;
  134. OpenMap(name, mapset, false); // used only for v.edit
  135. //Vect_build_partial(mapInfo, GV_BUILD_NONE, stderr);
  136. //Vect_build(mapInfo, stderr);
  137. return;
  138. }
  139. /*
  140. \brief Conversion from geographic coordinates (east, north)
  141. to screen (x, y)
  142. TODO: 3D stuff...
  143. \param[in] east,north,depth geographical coordinates
  144. \param[out] x, y, z screen coordinates
  145. \return
  146. */
  147. void DisplayDriver::Cell2Pixel(double east, double north, double depth,
  148. double *x, double *y, double *z)
  149. {
  150. double n, w;
  151. /*
  152. *x = int((east - region.map_west) / region.map_res);
  153. *y = int((region.map_north - north) / region.map_res);
  154. */
  155. w = region.center_easting - (region.map_width / 2) * region.map_res;
  156. n = region.center_northing + (region.map_height / 2) * region.map_res;
  157. /*
  158. *x = int((east - w) / region.map_res);
  159. *y = int((n - north) / region.map_res);
  160. */
  161. if (x)
  162. *x = (east - w) / region.map_res;
  163. if (y)
  164. *y = (n - north) / region.map_res;
  165. if (z)
  166. *z = 0.;
  167. return;
  168. }
  169. /**
  170. \brief Calculate distance in pixels
  171. \todo LL projection
  172. \param dist real distance
  173. */
  174. double DisplayDriver::DistanceInPixels(double dist)
  175. {
  176. double x;
  177. Cell2Pixel(region.map_west + dist, region.map_north, 0.0, &x, NULL, NULL);
  178. return std::sqrt(x * x);
  179. }
  180. /**
  181. \brief Set geographical region
  182. Region must be upgraded because of Cell2Pixel().
  183. \param[in] north,south,east,west,ns_res,ew_res region settings
  184. \return
  185. */
  186. void DisplayDriver::SetRegion(double north, double south, double east, double west,
  187. double ns_res, double ew_res,
  188. double center_easting, double center_northing,
  189. double map_width, double map_height)
  190. {
  191. region.box.N = north;
  192. region.box.S = south;
  193. region.box.E = east;
  194. region.box.W = west;
  195. region.box.T = PORT_DOUBLE_MAX;
  196. region.box.B = -PORT_DOUBLE_MAX;
  197. region.ns_res = ns_res;
  198. region.ew_res = ew_res;
  199. region.center_easting = center_easting;
  200. region.center_northing = center_northing;
  201. region.map_width = map_width;
  202. region.map_height = map_height;
  203. // calculate real region
  204. region.map_res = (region.ew_res > region.ns_res) ? region.ew_res : region.ns_res;
  205. region.map_west = region.center_easting - (region.map_width / 2.) * region.map_res;
  206. region.map_north = region.center_northing + (region.map_height / 2.) * region.map_res;
  207. return;
  208. }
  209. /*
  210. \brief Set settings for displaying vector feature
  211. E.g. line width, color, ...
  212. \param[in] lineWidth,... settgings
  213. \return
  214. */
  215. void DisplayDriver::UpdateSettings(unsigned long highlight,
  216. bool ehighlightDupl, unsigned long chighlightDupl,
  217. bool ePoint, unsigned long cPoint, /* enabled, color */
  218. bool eLine, unsigned long cLine,
  219. bool eBoundaryNo, unsigned long cBoundaryNo,
  220. bool eBoundaryOne, unsigned long cBoundaryOne,
  221. bool eBoundaryTwo, unsigned long cBoundaryTwo,
  222. bool eCentroidIn, unsigned long cCentroidIn,
  223. bool eCentroidOut, unsigned long cCentroidOut,
  224. bool eCentroidDup, unsigned long cCentroidDup,
  225. bool eNodeOne, unsigned long cNodeOne,
  226. bool eNodeTwo, unsigned long cNodeTwo,
  227. bool eVertex, unsigned long cVertex,
  228. bool eArea, unsigned long cArea,
  229. bool eDirection, unsigned long cDirection,
  230. int lineWidth, int alpha)
  231. {
  232. settings.highlight.Set(highlight);
  233. settings.highlightDupl.enabled = ehighlightDupl;
  234. settings.highlightDupl.color.Set(chighlightDupl);
  235. settings.point.enabled = ePoint;
  236. settings.point.color.Set(cPoint);
  237. settings.line.enabled = eLine;
  238. settings.line.color.Set(cLine);
  239. settings.boundaryNo.enabled = eBoundaryNo;
  240. settings.boundaryNo.color.Set(cBoundaryNo);
  241. settings.boundaryOne.enabled = eBoundaryOne;
  242. settings.boundaryOne.color.Set(cBoundaryOne);
  243. settings.boundaryTwo.enabled = eBoundaryTwo;
  244. settings.boundaryTwo.color.Set(cBoundaryTwo);
  245. settings.centroidIn.enabled = eCentroidIn;
  246. settings.centroidIn.color.Set(cCentroidIn);
  247. settings.centroidOut.enabled = eCentroidOut;
  248. settings.centroidOut.color.Set(cCentroidOut);
  249. settings.centroidDup.enabled = eCentroidDup;
  250. settings.centroidDup.color.Set(cCentroidDup);
  251. settings.nodeOne.enabled = eNodeOne;
  252. settings.nodeOne.color.Set(cNodeOne);
  253. settings.nodeTwo.enabled = eNodeTwo;
  254. settings.nodeTwo.color.Set(cNodeTwo);
  255. settings.vertex.enabled = eVertex;
  256. settings.vertex.color.Set(cVertex);
  257. settings.area.enabled = eArea;
  258. settings.area.color.Set(cArea);
  259. settings.area.color.Set(settings.area.color.Red(),
  260. settings.area.color.Green(),
  261. settings.area.color.Blue(),
  262. alpha);
  263. settings.direction.enabled = eDirection;
  264. settings.direction.color.Set(cDirection);
  265. settings.lineWidth = lineWidth;
  266. return;
  267. }
  268. /**
  269. \brief Prints gId: dcIds
  270. Useful for debugging purposes.
  271. \param
  272. \return
  273. */
  274. void DisplayDriver::PrintIds()
  275. {
  276. std::cerr << "topology.highlight: " << topology.highlight << std::endl;
  277. std::cerr << "topology.point: " << topology.point << std::endl;
  278. std::cerr << "topology.line: " << topology.line << std::endl;
  279. std::cerr << "topology.boundaryNo: " << topology.boundaryNo << std::endl;
  280. std::cerr << "topology.boundaryOne: " << topology.boundaryOne << std::endl;
  281. std::cerr << "topology.boundaryTwo: " << topology.boundaryTwo << std::endl;
  282. std::cerr << "topology.centroidIn: " << topology.centroidIn << std::endl;
  283. std::cerr << "topology.centroidOut: " << topology.centroidOut << std::endl;
  284. std::cerr << "topology.centroidDup: " << topology.centroidDup << std::endl;
  285. std::cerr << "topology.nodeOne: " << topology.nodeOne << std::endl;
  286. std::cerr << "topology.nodeTwo: " << topology.nodeTwo << std::endl;
  287. std::cerr << "topology.vertex: " << topology.vertex << std::endl;
  288. std::cerr << std::endl << "nobjects: "
  289. << topology.point * 2 + // cross
  290. topology.line +
  291. topology.boundaryNo +
  292. topology.boundaryOne +
  293. topology.boundaryTwo +
  294. topology.centroidIn * 2 +
  295. topology.centroidOut * 2 +
  296. topology.centroidDup * 2 +
  297. topology.nodeOne * 2 +
  298. topology.nodeTwo * 2 +
  299. topology.vertex * 2 << std::endl;
  300. std::cerr << "selected: ";
  301. for (int i = 0; i < selected.ids->n_values; i++) {
  302. std::cerr << selected.ids->value[i] << " ";
  303. }
  304. std::cerr << std::endl;
  305. return;
  306. }
  307. /**
  308. \brief Reset topology structure.
  309. \return
  310. */
  311. void DisplayDriver::ResetTopology()
  312. {
  313. topology.highlight = 0;
  314. topology.point = 0;
  315. topology.line = 0;
  316. topology.boundaryNo = 0;
  317. topology.boundaryOne = 0;
  318. topology.boundaryTwo = 0;
  319. topology.centroidIn = 0;
  320. topology.centroidOut = 0;
  321. topology.centroidDup = 0;
  322. topology.nodeOne = 0;
  323. topology.nodeTwo = 0;
  324. topology.vertex = 0;
  325. return;
  326. }
  327. /**
  328. \brief Convert vect list to std::vector
  329. \param list vect list
  330. \return std::vector
  331. */
  332. std::vector<int> DisplayDriver::ListToVector(struct ilist *list)
  333. {
  334. std::vector<int> vect;
  335. if (!list)
  336. return vect;
  337. for (int i = 0; i < list->n_values; i++) {
  338. vect.push_back(list->value[i]);
  339. }
  340. return vect;
  341. }
  342. /**
  343. \brief Convert std::vector to vect list
  344. \param list vect list
  345. \param vec std::vector instance
  346. \return number of items
  347. \return -1 on error
  348. */
  349. int DisplayDriver::VectorToList(struct ilist *list, const std::vector<int>& vec)
  350. {
  351. if (!list)
  352. return -1;
  353. Vect_reset_list(list);
  354. for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end();
  355. i != e; ++i) {
  356. Vect_list_append(list, *i);
  357. }
  358. return list->n_values;
  359. }
  360. /**
  361. \brief Get bounding box of (opened) vector map layer
  362. \return (w,s,b,e,n,t)
  363. */
  364. std::vector<double> DisplayDriver::GetMapBoundingBox()
  365. {
  366. std::vector<double> region;
  367. BOUND_BOX bbox;
  368. if (!mapInfo) {
  369. return region;
  370. }
  371. Vect_get_map_box(mapInfo, &bbox);
  372. region.push_back(bbox.W);
  373. region.push_back(bbox.S);
  374. region.push_back(bbox.B);
  375. region.push_back(bbox.E);
  376. region.push_back(bbox.N);
  377. region.push_back(bbox.T);
  378. return region;
  379. }
  380. /**
  381. \brief Error messages handling
  382. \param msg message
  383. \param type type message (MSG, WARN, ERR)
  384. \return 0
  385. */
  386. int print_error(const char *msg, int type)
  387. {
  388. fprintf(stderr, "%s", msg);
  389. return 0;
  390. }