driver.cpp 36 KB

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