select.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. #include <stdlib.h>
  2. #include <grass/gis.h>
  3. #include <grass/vector.h>
  4. #include <grass/glocale.h>
  5. #include "proto.h"
  6. void 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;
  12. int nalines, aline, ltype;
  13. struct line_pnts *APoints, *BPoints;
  14. struct ilist *BoundList, *LList;
  15. struct boxlist *List, *TmpList;
  16. #ifdef HAVE_GEOS
  17. initGEOS(G_message, G_fatal_error);
  18. GEOSGeometry *AGeom = NULL;
  19. #else
  20. void *AGeom = NULL;
  21. #endif
  22. nskipped[0] = nskipped[1] = 0;
  23. APoints = Vect_new_line_struct();
  24. BPoints = Vect_new_line_struct();
  25. List = Vect_new_boxlist(1);
  26. TmpList = Vect_new_boxlist(1);
  27. BoundList = Vect_new_list();
  28. LList = Vect_new_list();
  29. nalines = Vect_get_num_lines(aIn);
  30. /* Lines in A. Go through all lines and mark those that meets condition */
  31. if (atype & (GV_POINTS | GV_LINES)) {
  32. G_message(_("Processing features..."));
  33. G_percent(0, nalines, 2);
  34. for (aline = 1; aline <= nalines; aline++) {
  35. struct bound_box abox;
  36. G_debug(3, "aline = %d", aline);
  37. G_percent(aline, nalines, 2); /* must be before any continue */
  38. /* Check category */
  39. if (!cat_flag && Vect_get_line_cat(aIn, aline, afield) < 0) {
  40. nskipped[0]++;
  41. continue;
  42. }
  43. /* Read line and check type */
  44. if (operator != OP_OVERLAP) {
  45. #ifdef HAVE_GEOS
  46. AGeom = Vect_read_line_geos(aIn, aline, &ltype);
  47. #endif
  48. if (!(ltype & (GV_POINT | GV_LINE)))
  49. continue;
  50. if (!AGeom)
  51. G_fatal_error(_("Unable to read line id %d from vector map <%s>"),
  52. aline, Vect_get_full_name(aIn));
  53. }
  54. else {
  55. ltype = Vect_read_line(aIn, APoints, NULL, aline);
  56. }
  57. if (!(ltype & atype))
  58. continue;
  59. Vect_get_line_box(aIn, aline, &abox);
  60. /* Check if this line overlaps any feature in B */
  61. /* x Lines in B */
  62. if (btype & (GV_POINTS | GV_LINES)) {
  63. int found = 0;
  64. /* Lines */
  65. Vect_select_lines_by_box(bIn, &abox, btype, List);
  66. for (i = 0; i < List->n_values; i++) {
  67. int bline;
  68. bline = List->id[i];
  69. G_debug(3, " bline = %d", bline);
  70. /* Check category */
  71. if (!cat_flag &&
  72. Vect_get_line_cat(bIn, bline, bfield) < 0) {
  73. nskipped[1]++;
  74. continue;
  75. }
  76. if (operator != OP_OVERLAP) {
  77. #ifdef HAVE_GEOS
  78. if(line_relate_geos(bIn, AGeom,
  79. bline, operator, relate)) {
  80. found = 1;
  81. break;
  82. }
  83. #endif
  84. }
  85. else {
  86. Vect_read_line(bIn, BPoints, NULL, bline);
  87. if (Vect_line_check_intersection2(APoints, BPoints, 0)) {
  88. found = 1;
  89. break;
  90. }
  91. }
  92. }
  93. if (found) {
  94. ALines[aline] = 1;
  95. continue; /* Go to next A line */
  96. }
  97. }
  98. /* x Areas in B. */
  99. if (btype & GV_AREA) {
  100. Vect_select_areas_by_box(bIn, &abox, List);
  101. for (i = 0; i < List->n_values; i++) {
  102. int barea;
  103. barea = List->id[i];
  104. G_debug(3, " barea = %d", barea);
  105. if (Vect_get_area_cat(bIn, barea, bfield) < 0) {
  106. nskipped[1]++;
  107. continue;
  108. }
  109. if (operator != OP_OVERLAP) {
  110. #ifdef HAVE_GEOS
  111. if(area_relate_geos(bIn, AGeom,
  112. barea, operator, relate)) {
  113. ALines[aline] = 1;
  114. break;
  115. }
  116. #endif
  117. }
  118. else {
  119. if (line_overlap_area(APoints, bIn, barea)) {
  120. ALines[aline] = 1;
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. if (operator != OP_OVERLAP) {
  127. #ifdef HAVE_GEOS
  128. GEOSGeom_destroy(AGeom);
  129. #endif
  130. AGeom = NULL;
  131. }
  132. }
  133. }
  134. /* Areas in A. */
  135. if (atype & GV_AREA) {
  136. int aarea, naareas;
  137. G_message(_("Processing areas..."));
  138. naareas = Vect_get_num_areas(aIn);
  139. G_percent(0, naareas, 2);
  140. for (aarea = 1; aarea <= naareas; aarea++) {
  141. struct bound_box abox;
  142. G_percent(aarea, naareas, 1);
  143. if (Vect_get_area_cat(aIn, aarea, afield) < 0) {
  144. nskipped[0]++;
  145. continue;
  146. }
  147. Vect_get_area_box(aIn, aarea, &abox);
  148. abox.T = PORT_DOUBLE_MAX;
  149. abox.B = -PORT_DOUBLE_MAX;
  150. if (operator != OP_OVERLAP) {
  151. #ifdef HAVE_GEOS
  152. AGeom = Vect_read_area_geos(aIn, aarea);
  153. #endif
  154. if (!AGeom)
  155. G_fatal_error(_("Unable to read area id %d from vector map <%s>"),
  156. aarea, Vect_get_full_name(aIn));
  157. }
  158. /* x Lines in B */
  159. if (btype & (GV_POINTS | GV_LINES)) {
  160. Vect_select_lines_by_box(bIn, &abox, btype, List);
  161. for (i = 0; i < List->n_values; i++) {
  162. int bline;
  163. bline = List->id[i];
  164. if (!cat_flag &&
  165. Vect_get_line_cat(bIn, bline, bfield) < 0) {
  166. nskipped[1]++;
  167. continue;
  168. }
  169. if (operator != OP_OVERLAP) {
  170. #ifdef HAVE_GEOS
  171. if(line_relate_geos(bIn, AGeom,
  172. bline, operator, relate)) {
  173. add_aarea(aIn, aarea, ALines, AAreas);
  174. break;
  175. }
  176. #endif
  177. }
  178. else {
  179. Vect_read_line(bIn, BPoints, NULL, bline);
  180. if (line_overlap_area(BPoints, aIn, aarea)) {
  181. add_aarea(aIn, aarea, ALines, AAreas);
  182. continue;
  183. }
  184. }
  185. }
  186. }
  187. /* x Areas in B */
  188. if (btype & GV_AREA) {
  189. int naisles;
  190. int found = 0;
  191. /* List of areas B */
  192. /* Make a list of features forming area A */
  193. Vect_reset_list(LList);
  194. Vect_get_area_boundaries(aIn, aarea, BoundList);
  195. for (i = 0; i < BoundList->n_values; i++) {
  196. Vect_list_append(LList, abs(BoundList->value[i]));
  197. }
  198. naisles = Vect_get_area_num_isles(aIn, aarea);
  199. for (i = 0; i < naisles; i++) {
  200. int j, aisle;
  201. aisle = Vect_get_area_isle(aIn, aarea, i);
  202. Vect_get_isle_boundaries(aIn, aisle, BoundList);
  203. for (j = 0; j < BoundList->n_values; j++) {
  204. Vect_list_append(LList, BoundList->value[j]);
  205. }
  206. }
  207. Vect_select_areas_by_box(bIn, &abox, TmpList);
  208. for (i = 0; i < LList->n_values; i++) {
  209. int j;
  210. aline = abs(LList->value[i]);
  211. Vect_read_line(aIn, APoints, NULL, aline);
  212. for (j = 0; j < TmpList->n_values; j++) {
  213. int barea, bcentroid;
  214. barea = TmpList->id[j];
  215. G_debug(3, " barea = %d", barea);
  216. if (Vect_get_area_cat(bIn, barea, bfield) < 0) {
  217. nskipped[1]++;
  218. continue;
  219. }
  220. /* Check if any centroid of area B is in area A.
  221. * This test is important in if area B is completely within area A */
  222. if ((bcentroid = Vect_get_area_centroid(bIn, barea)) > 0)
  223. Vect_read_line(bIn, BPoints, NULL, bcentroid);
  224. else {
  225. double x, y;
  226. Vect_get_point_in_area(bIn, barea, &x, &y);
  227. Vect_reset_line(BPoints);
  228. Vect_append_point(BPoints, x, y, 0.0);
  229. }
  230. if (operator != OP_OVERLAP) {
  231. #ifdef HAVE_GEOS
  232. if(area_relate_geos(bIn, AGeom,
  233. barea, operator, relate)) {
  234. found = 1;
  235. break;
  236. }
  237. #endif
  238. }
  239. else {
  240. if (Vect_point_in_area(BPoints->x[0], BPoints->y[0], aIn,
  241. aarea, &abox)) {
  242. found = 1;
  243. break;
  244. }
  245. /* Check intersectin of lines from List with area B */
  246. if (line_overlap_area(APoints, bIn, barea)) {
  247. found = 1;
  248. break;
  249. }
  250. }
  251. }
  252. if (found) {
  253. add_aarea(aIn, aarea, ALines, AAreas);
  254. break;
  255. }
  256. }
  257. }
  258. if (operator != OP_OVERLAP) {
  259. #ifdef HAVE_GEOS
  260. GEOSGeom_destroy(AGeom);
  261. #endif
  262. AGeom = NULL;
  263. }
  264. }
  265. }
  266. Vect_destroy_line_struct(APoints);
  267. Vect_destroy_line_struct(BPoints);
  268. Vect_destroy_list(BoundList);
  269. Vect_destroy_list(LList);
  270. Vect_destroy_boxlist(List);
  271. Vect_destroy_boxlist(TmpList);
  272. return;
  273. }