select.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include <stdlib.h>
  2. #include <grass/gis.h>
  3. #include <grass/vector.h>
  4. #include <grass/glocale.h>
  5. #include "proto.h"
  6. int select_lines(struct Map_info *aIn, int atype, int afield,
  7. struct Map_info *bIn, int btype, int bfield,
  8. int cat_flag, int operator, const char *relate,
  9. int *ALines, int *AAreas, int* nskipped)
  10. {
  11. int i, ai;
  12. int nblines, bline, ltype;
  13. int nfound = 0;
  14. struct line_pnts *APoints, *BPoints;
  15. struct line_pnts *OPoints, **IPoints;
  16. int isle, nisles, isles_alloc;
  17. struct ilist *BoundList;
  18. struct boxlist *List;
  19. #ifdef HAVE_GEOS
  20. initGEOS(G_message, G_fatal_error);
  21. GEOSGeometry *BGeom = NULL;
  22. #else
  23. void *BGeom = NULL;
  24. #endif
  25. nskipped[0] = nskipped[1] = 0;
  26. APoints = Vect_new_line_struct();
  27. BPoints = Vect_new_line_struct();
  28. OPoints = Vect_new_line_struct();
  29. isles_alloc = 10;
  30. IPoints = G_malloc(isles_alloc * sizeof(struct line_pnts *));
  31. for (i = 0; i < isles_alloc; i++)
  32. IPoints[i] = Vect_new_line_struct();
  33. nisles = 0;
  34. List = Vect_new_boxlist(1);
  35. BoundList = Vect_new_list();
  36. nblines = Vect_get_num_lines(bIn);
  37. /* Lines in B */
  38. if (btype & (GV_POINTS | GV_LINES)) {
  39. G_message(_("Processing features..."));
  40. G_percent(0, nblines, 2);
  41. for (bline = 1; bline <= nblines; bline++) {
  42. struct bound_box bbox;
  43. G_debug(3, "bline = %d", bline);
  44. G_percent(bline, nblines, 1); /* must be before any continue */
  45. /* Check type */
  46. ltype = Vect_get_line_type(bIn, bline);
  47. if (!(ltype & btype))
  48. continue;
  49. /* Check category */
  50. if (!cat_flag && Vect_get_line_cat(bIn, bline, bfield) < 0) {
  51. nskipped[1]++;
  52. continue;
  53. }
  54. Vect_reset_line(BPoints);
  55. Vect_get_line_box(bIn, bline, &bbox);
  56. /* Check if this line overlaps any feature in A */
  57. /* x Lines in A */
  58. if (atype & (GV_POINTS | GV_LINES)) {
  59. /* Lines */
  60. Vect_select_lines_by_box(aIn, &bbox, atype, List);
  61. for (ai = 0; ai < List->n_values; ai++) {
  62. int aline;
  63. aline = List->id[ai];
  64. G_debug(3, " aline = %d", aline);
  65. if (ALines[aline] == 1)
  66. continue;
  67. /* Check type */
  68. ltype = Vect_get_line_type(aIn, aline);
  69. if (!(ltype & atype))
  70. continue;
  71. /* Check category */
  72. if (!cat_flag &&
  73. Vect_get_line_cat(aIn, aline, afield) < 0) {
  74. nskipped[0]++;
  75. continue;
  76. }
  77. if (operator != OP_OVERLAP) {
  78. #ifdef HAVE_GEOS
  79. if (!BGeom)
  80. BGeom = Vect_read_line_geos(bIn, bline, &ltype);
  81. if (!BGeom)
  82. G_fatal_error(_("Unable to read line id %d from vector map <%s>"),
  83. bline, Vect_get_full_name(bIn));
  84. if (line_relate_geos(aIn, BGeom, aline,
  85. operator, relate)) {
  86. ALines[aline] = 1;
  87. nfound += 1;
  88. }
  89. #endif
  90. }
  91. else {
  92. if (BPoints->n_points == 0)
  93. Vect_read_line(bIn, BPoints, NULL, bline);
  94. Vect_read_line(aIn, APoints, NULL, aline);
  95. if (Vect_line_check_intersection2(BPoints, APoints, 0)) {
  96. ALines[aline] = 1;
  97. nfound += 1;
  98. }
  99. }
  100. }
  101. }
  102. /* x Areas in A. */
  103. if (atype & GV_AREA) {
  104. Vect_select_areas_by_box(aIn, &bbox, List);
  105. for (ai = 0; ai < List->n_values; ai++) {
  106. int aarea;
  107. aarea = List->id[ai];
  108. G_debug(3, " aarea = %d", aarea);
  109. if (AAreas[aarea] == 1)
  110. continue;
  111. if (Vect_get_area_centroid(aIn, aarea) < 1)
  112. continue;
  113. if (!cat_flag &&
  114. Vect_get_area_cat(aIn, aarea, afield) < 0) {
  115. nskipped[0]++;
  116. continue;
  117. }
  118. if (operator != OP_OVERLAP) {
  119. #ifdef HAVE_GEOS
  120. if (!BGeom)
  121. BGeom = Vect_read_line_geos(bIn, bline, &ltype);
  122. if (!BGeom)
  123. G_fatal_error(_("Unable to read line id %d from vector map <%s>"),
  124. bline, Vect_get_full_name(bIn));
  125. if (area_relate_geos(aIn, BGeom, aarea,
  126. operator, relate)) {
  127. add_aarea(aIn, aarea, ALines, AAreas);
  128. nfound += 1;
  129. }
  130. #endif
  131. }
  132. else {
  133. if (BPoints->n_points == 0)
  134. Vect_read_line(bIn, BPoints, NULL, bline);
  135. Vect_get_area_points(aIn, aarea, OPoints);
  136. nisles = Vect_get_area_num_isles(aIn, aarea);
  137. if (nisles >= isles_alloc) {
  138. IPoints = G_realloc(IPoints, (nisles + 10) * sizeof(struct line_pnts *));
  139. for (i = isles_alloc; i < nisles + 10; i++)
  140. IPoints[i] = Vect_new_line_struct();
  141. isles_alloc = nisles + 10;
  142. }
  143. for (i = 0; i < nisles; i++) {
  144. isle = Vect_get_area_isle(aIn, aarea, i);
  145. Vect_get_isle_points(aIn, isle, IPoints[i]);
  146. }
  147. if (line_overlap_area(BPoints, OPoints, IPoints, nisles)) {
  148. add_aarea(aIn, aarea, ALines, AAreas);
  149. nfound += 1;
  150. }
  151. }
  152. }
  153. }
  154. #ifdef HAVE_GEOS
  155. if (BGeom != NULL) {
  156. GEOSGeom_destroy(BGeom);
  157. BGeom = NULL;
  158. }
  159. #endif
  160. }
  161. }
  162. /* Areas in B. */
  163. if (btype & GV_AREA) {
  164. int barea, nbareas, bcentroid;
  165. G_message(_("Processing areas..."));
  166. nbareas = Vect_get_num_areas(bIn);
  167. G_percent(0, nbareas, 1);
  168. for (barea = 1; barea <= nbareas; barea++) {
  169. struct bound_box bbox;
  170. G_percent(barea, nbareas, 2);
  171. if ((bcentroid = Vect_get_area_centroid(bIn, barea)) < 1)
  172. continue;
  173. if (!cat_flag &&
  174. Vect_get_area_cat(bIn, barea, bfield) < 0) {
  175. nskipped[1]++;
  176. continue;
  177. }
  178. Vect_reset_line(BPoints);
  179. Vect_get_area_box(bIn, barea, &bbox);
  180. bbox.T = PORT_DOUBLE_MAX;
  181. bbox.B = -PORT_DOUBLE_MAX;
  182. /* x Lines in A */
  183. if (atype & (GV_POINTS | GV_LINES)) {
  184. Vect_select_lines_by_box(aIn, &bbox, atype, List);
  185. for (ai = 0; ai < List->n_values; ai++) {
  186. int aline;
  187. aline = List->id[ai];
  188. if (ALines[aline] == 1)
  189. continue;
  190. /* Check type */
  191. ltype = Vect_get_line_type(aIn, aline);
  192. if (!(ltype & atype))
  193. continue;
  194. if (!cat_flag &&
  195. Vect_get_line_cat(aIn, aline, afield) < 0) {
  196. nskipped[0]++;
  197. continue;
  198. }
  199. if (operator != OP_OVERLAP) {
  200. #ifdef HAVE_GEOS
  201. if (!BGeom)
  202. BGeom = Vect_read_area_geos(bIn, barea);
  203. if (!BGeom)
  204. G_fatal_error(_("Unable to read area id %d from vector map <%s>"),
  205. barea, Vect_get_full_name(bIn));
  206. if (line_relate_geos(aIn, BGeom, aline,
  207. operator, relate)) {
  208. ALines[aline] = 1;
  209. nfound += 1;
  210. }
  211. #endif
  212. }
  213. else {
  214. if (BPoints->n_points == 0) {
  215. Vect_read_line(bIn, BPoints, NULL, bcentroid);
  216. Vect_get_area_points(bIn, barea, OPoints);
  217. nisles = Vect_get_area_num_isles(bIn, barea);
  218. if (nisles >= isles_alloc) {
  219. IPoints = G_realloc(IPoints, (nisles + 10) * sizeof(struct line_pnts *));
  220. for (i = isles_alloc; i < nisles + 10; i++)
  221. IPoints[i] = Vect_new_line_struct();
  222. isles_alloc = nisles + 10;
  223. }
  224. for (i = 0; i < nisles; i++) {
  225. isle = Vect_get_area_isle(bIn, barea, i);
  226. Vect_get_isle_points(bIn, isle, IPoints[i]);
  227. }
  228. }
  229. Vect_read_line(aIn, APoints, NULL, aline);
  230. if (line_overlap_area(APoints, OPoints, IPoints, nisles)) {
  231. ALines[aline] = 1;
  232. nfound += 1;
  233. }
  234. }
  235. }
  236. }
  237. /* x Areas in A */
  238. if (atype & GV_AREA) {
  239. /* List of areas A */
  240. Vect_select_areas_by_box(aIn, &bbox, List);
  241. for (ai = 0; ai < List->n_values; ai++) {
  242. int found = 0;
  243. int aarea, acentroid;
  244. aarea = List->id[ai];
  245. G_debug(3, " aarea = %d", aarea);
  246. if (AAreas[aarea] == 1)
  247. continue;
  248. if ((acentroid = Vect_get_area_centroid(aIn, aarea)) < 1)
  249. continue;
  250. if (!cat_flag &&
  251. Vect_get_area_cat(aIn, aarea, afield) < 0) {
  252. nskipped[0]++;
  253. continue;
  254. }
  255. if (operator != OP_OVERLAP) {
  256. #ifdef HAVE_GEOS
  257. if (!BGeom)
  258. BGeom = Vect_read_area_geos(bIn, barea);
  259. if (!BGeom)
  260. G_fatal_error(_("Unable to read area id %d from vector map <%s>"),
  261. barea, Vect_get_full_name(bIn));
  262. if (area_relate_geos(aIn, BGeom, aarea,
  263. operator, relate)) {
  264. found = 1;
  265. }
  266. #endif
  267. }
  268. else {
  269. if (BPoints->n_points == 0) {
  270. Vect_read_line(bIn, BPoints, NULL, bcentroid);
  271. Vect_get_area_points(bIn, barea, OPoints);
  272. nisles = Vect_get_area_num_isles(bIn, barea);
  273. if (nisles >= isles_alloc) {
  274. IPoints = G_realloc(IPoints, (nisles + 10) * sizeof(struct line_pnts *));
  275. for (i = isles_alloc; i < nisles + 10; i++)
  276. IPoints[i] = Vect_new_line_struct();
  277. isles_alloc = nisles + 10;
  278. }
  279. for (i = 0; i < nisles; i++) {
  280. isle = Vect_get_area_isle(bIn, barea, i);
  281. Vect_get_isle_points(bIn, isle, IPoints[i]);
  282. }
  283. }
  284. /* A inside B ? */
  285. Vect_read_line(aIn, APoints, NULL, acentroid);
  286. if (line_overlap_area(APoints, OPoints, IPoints, nisles)) {
  287. found = 1;
  288. }
  289. /* B inside A ? */
  290. if (!found) {
  291. struct bound_box abox;
  292. Vect_get_area_box(aIn, aarea, &abox);
  293. abox.T = PORT_DOUBLE_MAX;
  294. abox.B = -PORT_DOUBLE_MAX;
  295. if (Vect_point_in_area(BPoints->x[0], BPoints->y[0], aIn,
  296. aarea, &abox)) {
  297. found = 1;
  298. }
  299. }
  300. /* A overlaps B ? */
  301. if (!found) {
  302. Vect_get_area_boundaries(aIn, aarea, BoundList);
  303. for (i = 0; i < BoundList->n_values; i++) {
  304. Vect_read_line(aIn, APoints, NULL, abs(BoundList->value[i]));
  305. if (line_overlap_area(APoints, OPoints, IPoints, nisles)) {
  306. found = 1;
  307. break;
  308. }
  309. }
  310. }
  311. if (!found) {
  312. int j, naisles;
  313. naisles = Vect_get_area_num_isles(aIn, aarea);
  314. for (j = 0; j < naisles; j++) {
  315. isle = Vect_get_area_isle(aIn, aarea, j);
  316. Vect_get_isle_boundaries(aIn, isle, BoundList);
  317. for (i = 0; i < BoundList->n_values; i++) {
  318. Vect_read_line(aIn, APoints, NULL, abs(BoundList->value[i]));
  319. if (line_overlap_area(APoints, OPoints, IPoints, nisles)) {
  320. found = 1;
  321. break;
  322. }
  323. }
  324. if (found)
  325. break;
  326. }
  327. }
  328. }
  329. if (found) {
  330. add_aarea(aIn, aarea, ALines, AAreas);
  331. nfound += 1;
  332. }
  333. }
  334. }
  335. #ifdef HAVE_GEOS
  336. if (BGeom != NULL) {
  337. GEOSGeom_destroy(BGeom);
  338. BGeom = NULL;
  339. }
  340. #endif
  341. }
  342. }
  343. Vect_destroy_line_struct(APoints);
  344. Vect_destroy_line_struct(BPoints);
  345. Vect_destroy_list(BoundList);
  346. Vect_destroy_boxlist(List);
  347. return nfound;
  348. }