driver.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /**
  2. \file vdigit/driver.cpp
  3. \brief wxvdigit - Display driver
  4. This driver is designed for wxGUI (vector digitizer) - to draw
  5. 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. (C) 2008-2009 by Martin Landa, and the GRASS development team
  10. \author Martin Landa <landa.martin gmail.com>
  11. */
  12. #include <unistd.h>
  13. #include <cmath>
  14. #include "driver.h"
  15. #define MSG 0
  16. #define WARN 1
  17. #define ERR 2
  18. static int print_error(const char *, const int);
  19. static int print_percent(int);
  20. static void print_sentence (PyObject*, const int, const char *);
  21. static PyObject *logStream;
  22. static int message_id = 1;
  23. /**
  24. \brief Initialize driver
  25. Allocate given structures.
  26. \param[in,out] PseudoDC device where to draw vector objects
  27. \param[in,out] PseudoDC device where to draw vector objects (tmp, selected)
  28. \return
  29. */
  30. DisplayDriver::DisplayDriver(gwxPseudoDC *device, gwxPseudoDC *deviceTmp,
  31. PyObject *log)
  32. {
  33. G_gisinit(""); /* GRASS functions */
  34. mapInfo = NULL;
  35. dc = device;
  36. dcTmp = deviceTmp;
  37. logStream = log;
  38. points = Vect_new_line_struct();
  39. pointsScreen = new wxList();
  40. cats = Vect_new_cats_struct();
  41. selected.field = -1;
  42. selected.cats = Vect_new_list();
  43. selected.ids = Vect_new_list();
  44. selected.idsDupl = Vect_new_list();
  45. drawSegments = false;
  46. G_set_error_routine(&print_error);
  47. G_set_percent_routine(&print_percent);
  48. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  49. // Vect_set_fatal_error(GV_FATAL_PRINT);
  50. }
  51. /**
  52. \brief Destroy driver
  53. Close the map, deallocate given structures.
  54. \param
  55. \return
  56. */
  57. DisplayDriver::~DisplayDriver()
  58. {
  59. if (mapInfo)
  60. CloseMap();
  61. G_unset_error_routine();
  62. G_unset_percent_routine();
  63. Vect_destroy_line_struct(points);
  64. delete pointsScreen;
  65. Vect_destroy_cats_struct(cats);
  66. Vect_destroy_list(selected.cats);
  67. Vect_destroy_list(selected.ids);
  68. Vect_destroy_list(selected.idsDupl);
  69. }
  70. /**
  71. \brief Set device for drawing
  72. \param[in,out] PseudoDC device where to draw vector objects
  73. \return
  74. */
  75. void DisplayDriver::SetDevice(void *device)
  76. {
  77. dc = (gwxPseudoDC *) device;
  78. return;
  79. }
  80. /*
  81. \brief Close vector map layer
  82. \param void
  83. \return 0 on success
  84. \return non-zero on error
  85. */
  86. int DisplayDriver::CloseMap()
  87. {
  88. int ret;
  89. ret = -1;
  90. if (mapInfo) {
  91. if (mapInfo->mode == GV_MODE_RW) {
  92. /* rebuild topology */
  93. Vect_build_partial(mapInfo, GV_BUILD_NONE);
  94. Vect_build(mapInfo);
  95. }
  96. /* close map and store topo/cidx */
  97. ret = Vect_close(mapInfo);
  98. G_free ((void *) mapInfo);
  99. mapInfo = NULL;
  100. }
  101. return ret;
  102. }
  103. /**
  104. \brief Open vector map layer
  105. \param[in] mapname name of vector map
  106. \param[in] mapset name of mapset where the vector map layer is stored
  107. \return topo level
  108. \return -1 on error
  109. */
  110. int DisplayDriver::OpenMap(const char* mapname, const char *mapset, bool update)
  111. {
  112. int ret;
  113. if (!mapInfo)
  114. mapInfo = (struct Map_info *) G_malloc (sizeof (struct Map_info));
  115. // define open level (level 2: topology)
  116. Vect_set_open_level(2);
  117. // avoid GUI crash when G_fatal_error() is called (opening the vector map)
  118. Vect_set_fatal_error(GV_FATAL_PRINT);
  119. // open existing map
  120. if (!update) {
  121. ret = Vect_open_old(mapInfo, (char*) mapname, (char *) mapset);
  122. }
  123. else {
  124. ret = Vect_open_update(mapInfo, (char*) mapname, (char *) mapset);
  125. }
  126. if (ret == -1) { // error
  127. G_free((void *) mapInfo);
  128. mapInfo = NULL;
  129. }
  130. return ret;
  131. }
  132. /**
  133. \brief Reload vector map layer
  134. Close and open again. Needed for modification using v.edit.
  135. TODO: Get rid of that...
  136. \param
  137. \return
  138. */
  139. void DisplayDriver::ReloadMap()
  140. {
  141. // char* name = G_store(Vect_get_map_name(mapInfo)); ???
  142. char* name = G_store(mapInfo->name);
  143. char* mapset = G_store(Vect_get_mapset(mapInfo));
  144. Vect_close(mapInfo);
  145. mapInfo = NULL;
  146. OpenMap(name, mapset, false); // used only for v.edit
  147. //Vect_build_partial(mapInfo, GV_BUILD_NONE, stderr);
  148. //Vect_build(mapInfo, stderr);
  149. return;
  150. }
  151. /*
  152. \brief Conversion from geographic coordinates (east, north)
  153. to screen (x, y)
  154. TODO: 3D stuff...
  155. \param[in] east,north,depth geographical coordinates
  156. \param[out] x, y, z screen coordinates
  157. \return
  158. */
  159. void DisplayDriver::Cell2Pixel(double east, double north, double depth,
  160. double *x, double *y, double *z)
  161. {
  162. double n, w;
  163. /*
  164. *x = int((east - region.map_west) / region.map_res);
  165. *y = int((region.map_north - north) / region.map_res);
  166. */
  167. w = region.center_easting - (region.map_width / 2) * region.map_res;
  168. n = region.center_northing + (region.map_height / 2) * region.map_res;
  169. /*
  170. *x = int((east - w) / region.map_res);
  171. *y = int((n - north) / region.map_res);
  172. */
  173. if (x)
  174. *x = (east - w) / region.map_res;
  175. if (y)
  176. *y = (n - north) / region.map_res;
  177. if (z)
  178. *z = 0.;
  179. return;
  180. }
  181. /**
  182. \brief Calculate distance in pixels
  183. \todo LL projection
  184. \param dist real distance
  185. */
  186. double DisplayDriver::DistanceInPixels(double dist)
  187. {
  188. double x;
  189. Cell2Pixel(region.map_west + dist, region.map_north, 0.0, &x, NULL, NULL);
  190. return std::sqrt(x * x);
  191. }
  192. /**
  193. \brief Set geographical region
  194. Region must be upgraded because of Cell2Pixel().
  195. \param[in] north,south,east,west,ns_res,ew_res region settings
  196. \return
  197. */
  198. void DisplayDriver::SetRegion(double north, double south, double east, double west,
  199. double ns_res, double ew_res,
  200. double center_easting, double center_northing,
  201. double map_width, double map_height)
  202. {
  203. region.box.N = north;
  204. region.box.S = south;
  205. region.box.E = east;
  206. region.box.W = west;
  207. region.box.T = PORT_DOUBLE_MAX;
  208. region.box.B = -PORT_DOUBLE_MAX;
  209. region.ns_res = ns_res;
  210. region.ew_res = ew_res;
  211. region.center_easting = center_easting;
  212. region.center_northing = center_northing;
  213. region.map_width = map_width;
  214. region.map_height = map_height;
  215. // calculate real region
  216. region.map_res = (region.ew_res > region.ns_res) ? region.ew_res : region.ns_res;
  217. region.map_west = region.center_easting - (region.map_width / 2.) * region.map_res;
  218. region.map_north = region.center_northing + (region.map_height / 2.) * region.map_res;
  219. return;
  220. }
  221. /*
  222. \brief Set settings for displaying vector feature
  223. E.g. line width, color, ...
  224. \param[in] lineWidth,... settgings
  225. \return
  226. */
  227. void DisplayDriver::UpdateSettings(unsigned long highlight,
  228. bool ehighlightDupl, unsigned long chighlightDupl,
  229. bool ePoint, unsigned long cPoint, /* enabled, color */
  230. bool eLine, unsigned long cLine,
  231. bool eBoundaryNo, unsigned long cBoundaryNo,
  232. bool eBoundaryOne, unsigned long cBoundaryOne,
  233. bool eBoundaryTwo, unsigned long cBoundaryTwo,
  234. bool eCentroidIn, unsigned long cCentroidIn,
  235. bool eCentroidOut, unsigned long cCentroidOut,
  236. bool eCentroidDup, unsigned long cCentroidDup,
  237. bool eNodeOne, unsigned long cNodeOne,
  238. bool eNodeTwo, unsigned long cNodeTwo,
  239. bool eVertex, unsigned long cVertex,
  240. bool eArea, unsigned long cArea,
  241. bool eDirection, unsigned long cDirection,
  242. int lineWidth, int alpha)
  243. {
  244. settings.highlight.Set(highlight);
  245. settings.highlightDupl.enabled = ehighlightDupl;
  246. settings.highlightDupl.color.Set(chighlightDupl);
  247. settings.point.enabled = ePoint;
  248. settings.point.color.Set(cPoint);
  249. settings.line.enabled = eLine;
  250. settings.line.color.Set(cLine);
  251. settings.boundaryNo.enabled = eBoundaryNo;
  252. settings.boundaryNo.color.Set(cBoundaryNo);
  253. settings.boundaryOne.enabled = eBoundaryOne;
  254. settings.boundaryOne.color.Set(cBoundaryOne);
  255. settings.boundaryTwo.enabled = eBoundaryTwo;
  256. settings.boundaryTwo.color.Set(cBoundaryTwo);
  257. settings.centroidIn.enabled = eCentroidIn;
  258. settings.centroidIn.color.Set(cCentroidIn);
  259. settings.centroidOut.enabled = eCentroidOut;
  260. settings.centroidOut.color.Set(cCentroidOut);
  261. settings.centroidDup.enabled = eCentroidDup;
  262. settings.centroidDup.color.Set(cCentroidDup);
  263. settings.nodeOne.enabled = eNodeOne;
  264. settings.nodeOne.color.Set(cNodeOne);
  265. settings.nodeTwo.enabled = eNodeTwo;
  266. settings.nodeTwo.color.Set(cNodeTwo);
  267. settings.vertex.enabled = eVertex;
  268. settings.vertex.color.Set(cVertex);
  269. settings.area.enabled = eArea;
  270. settings.area.color.Set(cArea);
  271. settings.area.color.Set(settings.area.color.Red(),
  272. settings.area.color.Green(),
  273. settings.area.color.Blue(),
  274. alpha);
  275. settings.direction.enabled = eDirection;
  276. settings.direction.color.Set(cDirection);
  277. settings.lineWidth = lineWidth;
  278. return;
  279. }
  280. /**
  281. \brief Prints gId: dcIds
  282. Useful for debugging purposes.
  283. \param
  284. \return
  285. */
  286. void DisplayDriver::PrintIds()
  287. {
  288. std::cerr << "topology.highlight: " << topology.highlight << std::endl;
  289. std::cerr << "topology.point: " << topology.point << std::endl;
  290. std::cerr << "topology.line: " << topology.line << std::endl;
  291. std::cerr << "topology.boundaryNo: " << topology.boundaryNo << std::endl;
  292. std::cerr << "topology.boundaryOne: " << topology.boundaryOne << std::endl;
  293. std::cerr << "topology.boundaryTwo: " << topology.boundaryTwo << std::endl;
  294. std::cerr << "topology.centroidIn: " << topology.centroidIn << std::endl;
  295. std::cerr << "topology.centroidOut: " << topology.centroidOut << std::endl;
  296. std::cerr << "topology.centroidDup: " << topology.centroidDup << std::endl;
  297. std::cerr << "topology.nodeOne: " << topology.nodeOne << std::endl;
  298. std::cerr << "topology.nodeTwo: " << topology.nodeTwo << std::endl;
  299. std::cerr << "topology.vertex: " << topology.vertex << std::endl;
  300. std::cerr << std::endl << "nobjects: "
  301. << topology.point * 2 + // cross
  302. topology.line +
  303. topology.boundaryNo +
  304. topology.boundaryOne +
  305. topology.boundaryTwo +
  306. topology.centroidIn * 2 +
  307. topology.centroidOut * 2 +
  308. topology.centroidDup * 2 +
  309. topology.nodeOne * 2 +
  310. topology.nodeTwo * 2 +
  311. topology.vertex * 2 << std::endl;
  312. std::cerr << "selected: ";
  313. for (int i = 0; i < selected.ids->n_values; i++) {
  314. std::cerr << selected.ids->value[i] << " ";
  315. }
  316. std::cerr << std::endl;
  317. return;
  318. }
  319. /**
  320. \brief Reset topology structure.
  321. \return
  322. */
  323. void DisplayDriver::ResetTopology()
  324. {
  325. topology.highlight = 0;
  326. topology.point = 0;
  327. topology.line = 0;
  328. topology.boundaryNo = 0;
  329. topology.boundaryOne = 0;
  330. topology.boundaryTwo = 0;
  331. topology.centroidIn = 0;
  332. topology.centroidOut = 0;
  333. topology.centroidDup = 0;
  334. topology.nodeOne = 0;
  335. topology.nodeTwo = 0;
  336. topology.vertex = 0;
  337. return;
  338. }
  339. /**
  340. \brief Convert vect list to std::vector
  341. \param list vect list
  342. \return std::vector
  343. */
  344. std::vector<int> DisplayDriver::ListToVector(struct ilist *list)
  345. {
  346. std::vector<int> vect;
  347. if (!list)
  348. return vect;
  349. for (int i = 0; i < list->n_values; i++) {
  350. vect.push_back(list->value[i]);
  351. }
  352. return vect;
  353. }
  354. /**
  355. \brief Convert std::vector to vect list
  356. \param list vect list
  357. \param vec std::vector instance
  358. \return number of items
  359. \return -1 on error
  360. */
  361. int DisplayDriver::VectorToList(struct ilist *list, const std::vector<int>& vec)
  362. {
  363. if (!list)
  364. return -1;
  365. Vect_reset_list(list);
  366. for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end();
  367. i != e; ++i) {
  368. Vect_list_append(list, *i);
  369. }
  370. return list->n_values;
  371. }
  372. /**
  373. \brief Get bounding box of (opened) vector map layer
  374. \return (w,s,b,e,n,t)
  375. */
  376. std::vector<double> DisplayDriver::GetMapBoundingBox()
  377. {
  378. std::vector<double> region;
  379. struct bound_box bbox;
  380. if (!mapInfo) {
  381. return region;
  382. }
  383. Vect_get_map_box(mapInfo, &bbox);
  384. region.push_back(bbox.W);
  385. region.push_back(bbox.S);
  386. region.push_back(bbox.B);
  387. region.push_back(bbox.E);
  388. region.push_back(bbox.N);
  389. region.push_back(bbox.T);
  390. return region;
  391. }
  392. /*
  393. \brief Print one message, prefix inserted before each new line
  394. From lib/gis/error.c
  395. */
  396. void print_sentence (PyObject *pyFd, const int type, const char *msg)
  397. {
  398. char prefix[256];
  399. const char *start;
  400. char* sentence;
  401. switch (type) {
  402. case MSG:
  403. sprintf (prefix, "GRASS_INFO_MESSAGE(%d,%d): Vdigit: ", getpid(), message_id);
  404. break;
  405. case WARN:
  406. sprintf (prefix, "GRASS_INFO_WARNING(%d,%d): Vdigit: ", getpid(), message_id);
  407. break;
  408. case ERR:
  409. sprintf (prefix, "GRASS_INFO_ERROR(%d,%d): Vdigit: ", getpid(), message_id);
  410. break;
  411. }
  412. start = msg;
  413. PyFile_WriteString("\n", pyFd);
  414. while (*start != '\0') {
  415. const char *next = start;
  416. PyFile_WriteString(prefix, pyFd);
  417. while ( *next != '\0' ) {
  418. next++;
  419. if ( *next == '\n' ) {
  420. next++;
  421. break;
  422. }
  423. }
  424. sentence = (char *) G_malloc((next - start + 1) * sizeof (char));
  425. strncpy(sentence, start, next - start + 1);
  426. sentence[next-start] = '\0';
  427. PyFile_WriteString(sentence, pyFd);
  428. G_free((void *)sentence);
  429. PyFile_WriteString("\n", pyFd);
  430. start = next;
  431. }
  432. PyFile_WriteString("\n", pyFd);
  433. sprintf(prefix, "GRASS_INFO_END(%d,%d)\n", getpid(), message_id);
  434. PyFile_WriteString(prefix, pyFd);
  435. message_id++;
  436. }
  437. /*!
  438. \brief Print error/warning/message
  439. \param msg message buffer
  440. \param type message type
  441. \return 0
  442. */
  443. int print_error(const char *msg, const int type)
  444. {
  445. if (logStream) {
  446. print_sentence(logStream, type, msg);
  447. }
  448. else {
  449. fprintf(stderr, "Vdigit: %s\n", msg);
  450. }
  451. return 0;
  452. }
  453. /*!
  454. \brief Print percentage information
  455. \param x value
  456. \return 0
  457. */
  458. int print_percent(int x)
  459. {
  460. char msg[256];
  461. if (logStream) {
  462. sprintf(msg, "GRASS_INFO_PERCENT: %d\n", x);
  463. PyFile_WriteString(msg, logStream);
  464. }
  465. else {
  466. fprintf(stderr, "GRASS_INFO_PERCENT: %d\n", x);
  467. }
  468. return 0;
  469. }
  470. /**
  471. \brief Check if vector map is 3D
  472. \return True for 3D otherwise False
  473. */
  474. bool DisplayDriver::Is3D()
  475. {
  476. return (bool) Vect_is_3d(mapInfo);
  477. }