driver_select.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /**
  2. \file driver_select.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 Select vector objects by given bounding box
  17. If line id is already in the list of selected lines, then it will
  18. be excluded from this list.
  19. \param[in] x1,y1,z1,x2,y2,z3 bounding box definition
  20. \param[in] type feature type
  21. \param[in] onlyInside if true select only features inside
  22. of bounding box (not overlapping)
  23. \return number of selected features
  24. \return -1 on error
  25. */
  26. int DisplayDriver::SelectLinesByBox(double x1, double y1, double z1,
  27. double x2, double y2, double z2,
  28. int type, bool onlyInside)
  29. {
  30. if (!mapInfo)
  31. return -1;
  32. int line;
  33. struct ilist *list;
  34. struct line_pnts *bbox;
  35. drawSegments = false;
  36. drawSelected = true;
  37. selected.isId = true;
  38. list = Vect_new_list();
  39. bbox = Vect_new_line_struct();
  40. Vect_append_point(bbox, x1, y1, z1);
  41. Vect_append_point(bbox, x2, y1, z2);
  42. Vect_append_point(bbox, x2, y2, z1);
  43. Vect_append_point(bbox, x1, y2, z2);
  44. Vect_append_point(bbox, x1, y1, z1);
  45. Vect_select_lines_by_polygon(mapInfo, bbox,
  46. 0, NULL, /* isles */
  47. type, list);
  48. for (int i = 0; i < list->n_values; i++) {
  49. line = list->value[i];
  50. if (onlyInside) {
  51. bool inside;
  52. inside = true;
  53. Vect_read_line(mapInfo, points, cats, line);
  54. for (int p = 0; p < points->n_points; p++) {
  55. if (!Vect_point_in_poly(points->x[p], points->y[p],
  56. bbox)) {
  57. inside = false;
  58. break;
  59. }
  60. }
  61. if (!inside)
  62. continue; /* skip lines just overlapping bbox */
  63. }
  64. if (!IsSelected(line)) {
  65. Vect_list_append(selected.values, line);
  66. }
  67. else {
  68. Vect_list_delete(selected.values, line);
  69. }
  70. }
  71. Vect_destroy_line_struct(bbox);
  72. Vect_destroy_list(list);
  73. return list->n_values;
  74. }
  75. /**
  76. \brief Select vector feature by given point in given
  77. threshold
  78. Only one vector object can be selected. Bounding boxes of
  79. all segments are stores.
  80. \param[in] x,y point of searching
  81. \param[in] thresh threshold value where to search
  82. \param[in] type select vector object of given type
  83. \return point on line if line found
  84. */
  85. std::vector<double> DisplayDriver::SelectLineByPoint(double x, double y, double z,
  86. double thresh, int type, int with_z)
  87. {
  88. long int line;
  89. double px, py, pz;
  90. std::vector<double> p;
  91. drawSelected = true;
  92. selected.isId = true;
  93. line = Vect_find_line(mapInfo, x, y, z,
  94. type, thresh, with_z, 0);
  95. if (line > 0) {
  96. if (!IsSelected(line)) {
  97. Vect_list_append(selected.values, line);
  98. }
  99. else {
  100. Vect_list_delete(selected.values, line);
  101. }
  102. type = Vect_read_line (mapInfo, points, cats, line);
  103. Vect_line_distance (points, x, y, z, with_z,
  104. &px, &py, &pz,
  105. NULL, NULL, NULL);
  106. p.push_back(px);
  107. p.push_back(py);
  108. if (with_z) {
  109. p.push_back(pz);
  110. }
  111. }
  112. drawSegments = true;
  113. return p;
  114. }
  115. /**
  116. \brief Is vector object selected?
  117. \param[in] line id
  118. \return true if vector object is selected
  119. \return false if vector object is not selected
  120. */
  121. bool DisplayDriver::IsSelected(int line, bool force)
  122. {
  123. if (selected.isId || force) {
  124. if (Vect_val_in_list(selected.values, line))
  125. return true;
  126. }
  127. else {
  128. for (int i = 0; i < cats->n_cats; i++) {
  129. if (cats->field[i] == 1 && /* TODO: field */
  130. Vect_val_in_list(selected.values, cats->cat[i]))
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. /**
  137. \brief Get ids of selected objects
  138. \param[in] grassId if true return GRASS line ids
  139. if false return PseudoDC ids
  140. \return list of ids of selected vector objects
  141. */
  142. std::vector<int> DisplayDriver::GetSelected(bool grassId)
  143. {
  144. if (grassId)
  145. return ListToVector(selected.values);
  146. std::vector<int> dc_ids;
  147. if (!drawSegments) {
  148. dc_ids.push_back(1);
  149. }
  150. else {
  151. int npoints;
  152. Vect_read_line(mapInfo, points, NULL, selected.values->value[0]);
  153. npoints = points->n_points;
  154. for (int i = 1; i < 2 * npoints; i++) {
  155. dc_ids.push_back(i);
  156. }
  157. }
  158. return dc_ids;
  159. }
  160. /**
  161. \brief Get feature (grass) ids of duplicated objects
  162. \return list of ids
  163. */
  164. std::map<int, std::vector <int> > DisplayDriver::GetDuplicates()
  165. {
  166. std::map<int, std::vector<int> > ids;
  167. struct line_pnts *APoints, *BPoints;
  168. int line;
  169. APoints = Vect_new_line_struct();
  170. BPoints = Vect_new_line_struct();
  171. Vect_reset_list(selected.valuesDupl);
  172. for (int i = 0; i < selected.values->n_values; i++) {
  173. line = selected.values->value[i];
  174. if (IsDuplicated(line))
  175. continue;
  176. Vect_read_line(mapInfo, APoints, NULL, line);
  177. for (int j = 0; j < selected.values->n_values; j++) {
  178. if (i == j || IsDuplicated(selected.values->value[j]))
  179. continue;
  180. Vect_read_line(mapInfo, BPoints, NULL, selected.values->value[j]);
  181. if (Vect_line_check_duplicate (APoints, BPoints, WITHOUT_Z)) {
  182. if (ids.find(i) == ids.end()) {
  183. ids[i] = std::vector<int> ();
  184. ids[i].push_back(selected.values->value[i]);
  185. Vect_list_append(selected.valuesDupl, selected.values->value[i]);
  186. }
  187. ids[i].push_back(selected.values->value[j]);
  188. Vect_list_append(selected.valuesDupl, selected.values->value[j]);
  189. }
  190. }
  191. }
  192. Vect_destroy_line_struct(APoints);
  193. Vect_destroy_line_struct(BPoints);
  194. return ids;
  195. }
  196. /**
  197. \brief Check for already marked duplicates
  198. \param line line id
  199. \return 1 line already marked as duplicated
  200. \return 0 not duplicated
  201. */
  202. bool DisplayDriver::IsDuplicated(int line)
  203. {
  204. if (Vect_val_in_list(selected.valuesDupl, line))
  205. return true;
  206. return false;
  207. }
  208. /**
  209. \brief Set selected vector objects
  210. \param[in] list of GRASS ids to be set
  211. \param[in] cat if True expect categories instead of feature ids
  212. \return 1
  213. */
  214. int DisplayDriver::SetSelected(std::vector<int> id, bool cat)
  215. {
  216. drawSelected = true;
  217. VectorToList(selected.values, id);
  218. selected.isId = !cat;
  219. if (selected.values->n_values <= 0)
  220. drawSegments = false;
  221. return 1;
  222. }
  223. /**
  224. \brief Unselect selected vector features
  225. \param[in] list of GRASS feature ids
  226. \return number of selected features
  227. */
  228. int DisplayDriver::UnSelect(std::vector<int> id)
  229. {
  230. bool checkForDupl;
  231. checkForDupl = false;
  232. for (std::vector<int>::const_iterator i = id.begin(), e = id.end();
  233. i != e; ++i) {
  234. if (IsSelected(*i)) {
  235. Vect_list_delete(selected.values, *i);
  236. }
  237. if (settings.highlightDupl.enabled && IsDuplicated(*i)) {
  238. checkForDupl = true;
  239. }
  240. }
  241. if (checkForDupl) {
  242. GetDuplicates();
  243. }
  244. return selected.values->n_values;
  245. }
  246. /**
  247. \brief Get PseudoDC vertex id of selected line
  248. Set bounding box for vertices of line.
  249. \param[in] x,y coordinates of click
  250. \param[in] thresh threshold value
  251. \return id of center, left and right vertex
  252. \return 0 no line found
  253. \return -1 on error
  254. */
  255. std::vector<int> DisplayDriver::GetSelectedVertex(double x, double y, double thresh)
  256. {
  257. int startId;
  258. int line, type;
  259. int Gid, DCid;
  260. double vx, vy, vz; // vertex screen coordinates
  261. double dist, minDist;
  262. std::vector<int> returnId;
  263. // only one object can be selected
  264. if (selected.values->n_values != 1 || !drawSegments)
  265. return returnId;
  266. startId = 1;
  267. line = selected.values->value[0];
  268. type = Vect_read_line (mapInfo, points, cats, line);
  269. minDist = 0.0;
  270. Gid = -1;
  271. // find the closest vertex (x, y)
  272. DCid = 1;
  273. for(int idx = 0; idx < points->n_points; idx++) {
  274. dist = Vect_points_distance(x, y, 0.0,
  275. points->x[idx], points->y[idx], points->z[idx], 0);
  276. if (idx == 0) {
  277. minDist = dist;
  278. Gid = idx;
  279. }
  280. else {
  281. if (minDist > dist) {
  282. minDist = dist;
  283. Gid = idx;
  284. }
  285. }
  286. Cell2Pixel(points->x[idx], points->y[idx], points->z[idx],
  287. &vx, &vy, &vz);
  288. wxRect rect (wxPoint ((int) vx, (int) vy), wxPoint ((int) vx, (int) vy));
  289. dc->SetIdBounds(DCid, rect);
  290. DCid+=2;
  291. }
  292. if (minDist > thresh)
  293. return returnId;
  294. // desc = &(ids[line]);
  295. // translate id
  296. DCid = Gid * 2 + 1;
  297. // add selected vertex
  298. returnId.push_back(DCid);
  299. // left vertex
  300. if (DCid == startId) {
  301. returnId.push_back(-1);
  302. }
  303. else {
  304. returnId.push_back(DCid - 2);
  305. }
  306. // right vertex
  307. if (DCid == (points->n_points - 1) * 2 + startId) {
  308. returnId.push_back(-1);
  309. }
  310. else {
  311. returnId.push_back(DCid + 2);
  312. }
  313. return returnId;
  314. }
  315. /*!
  316. \brief Get minimal region extent of selected features
  317. \return n,s,w,e
  318. */
  319. std::vector<int> DisplayDriver::GetRegionSelected()
  320. {
  321. int line, area, nareas;
  322. std::vector<int> region;
  323. BOUND_BOX region_box, line_box;
  324. struct ilist *list, *list_tmp;
  325. list = list_tmp = NULL;
  326. G_zero(&region_box, sizeof(region_box));
  327. if (!selected.isId) { /* -> cats */
  328. list = Vect_new_list();
  329. list_tmp = Vect_new_list();
  330. /* can't use here
  331. *
  332. Vect_cidx_find_all(mapInfo, 1, GV_POINTS | GV_LINES,
  333. selected.values->value[i],
  334. list_tmp);
  335. */
  336. int type;
  337. bool found;
  338. for (int line = 1; line <= Vect_get_num_lines(mapInfo); line++) {
  339. type = Vect_read_line (mapInfo, NULL, cats, line);
  340. if (!(type & (GV_POINTS | GV_LINES)))
  341. continue;
  342. found = false;
  343. for (int i = 0; i < cats->n_cats && !found; i++) {
  344. for (int j = 0; j < selected.values->n_values && !found; j++) {
  345. if (cats->cat[i] == selected.values->value[j])
  346. found = true;
  347. }
  348. }
  349. if (found)
  350. Vect_list_append(list, line);
  351. }
  352. }
  353. else {
  354. list = selected.values;
  355. }
  356. nareas = Vect_get_num_areas(mapInfo);
  357. for (int i = 0; i < list->n_values; i++) {
  358. line = list->value[i];
  359. area = Vect_get_centroid_area(mapInfo, line);
  360. if (area > 0 && area <= nareas) {
  361. if (!Vect_get_area_box(mapInfo, area, &line_box))
  362. continue;
  363. }
  364. else {
  365. if (!Vect_get_line_box(mapInfo, line, &line_box))
  366. continue;
  367. }
  368. if (i == 0) {
  369. Vect_box_copy(&region_box, &line_box);
  370. }
  371. else {
  372. Vect_box_extend(&region_box, &line_box);
  373. }
  374. }
  375. if (list && list != selected.values) {
  376. Vect_destroy_list(list);
  377. }
  378. if (list_tmp)
  379. Vect_destroy_list(list_tmp);
  380. region.push_back(region_box.N);
  381. region.push_back(region_box.S);
  382. region.push_back(region_box.W);
  383. region.push_back(region_box.E);
  384. return region;
  385. }