main.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /****************************************************************************
  2. *
  3. * MODULE: v.select
  4. * AUTHOR(S): Radim Blazek <radim.blazek gmail.com> (original contributor)
  5. * Glynn Clements <glynn gclements.plus.com>
  6. * Markus Neteler <neteler itc.it>
  7. * Martin Landa <landa.martin gmail.com> (GEOS support)
  8. * Huidae Cho <grass4u gmail.com> (reverse flag fix)
  9. * PURPOSE: Select features from one map by features in another map.
  10. * COPYRIGHT: (C) 2003-2017, 2019 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General
  13. * Public License (>=v2). Read the file COPYING that
  14. * comes with GRASS for details.
  15. *
  16. *****************************************************************************/
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <grass/gis.h>
  21. #include <grass/vector.h>
  22. #include <grass/glocale.h>
  23. #include "proto.h"
  24. int main(int argc, char *argv[])
  25. {
  26. int iopt;
  27. int operator;
  28. int nskipped[2], native, nfound;
  29. int itype[2], ifield[2];
  30. int *ALines; /* List of lines: 0 do not output, 1 - write to output */
  31. int *AAreas; /* List of areas: 0 do not output, 1 - write area boundaries to output */
  32. int **cats, *ncats, *fields, nfields;
  33. struct GModule *module;
  34. struct GParm parm;
  35. struct GFlag flag;
  36. struct Map_info In[2], Out;
  37. struct field_info *IFi;
  38. int nlines, nareas;
  39. G_gisinit(argv[0]);
  40. module = G_define_module();
  41. G_add_keyword(_("vector"));
  42. G_add_keyword(_("geometry"));
  43. G_add_keyword(_("spatial query"));
  44. module->description =
  45. _("Selects features from vector map (A) by features from other vector map (B).");
  46. parse_options(&parm, &flag);
  47. if (G_parser(argc, argv))
  48. exit(EXIT_FAILURE);
  49. if (parm.operator->answer[0] == 'e')
  50. operator = OP_EQUALS;
  51. else if (parm.operator->answer[0] == 'd') {
  52. /* operator = OP_DISJOINT; */
  53. operator = OP_INTERSECTS;
  54. flag.reverse->answer = YES;
  55. }
  56. else if (parm.operator->answer[0] == 'i')
  57. operator = OP_INTERSECTS;
  58. else if (parm.operator->answer[0] == 't')
  59. operator = OP_TOUCHES;
  60. else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'r')
  61. operator = OP_CROSSES;
  62. else if (parm.operator->answer[0] == 'w')
  63. operator = OP_WITHIN;
  64. else if (parm.operator->answer[0] == 'c' && parm.operator->answer[1] == 'o')
  65. operator = OP_CONTAINS;
  66. else if (parm.operator->answer[0] == 'o') {
  67. if (strcmp(parm.operator->answer, "overlaps") == 0)
  68. operator = OP_OVERLAPS;
  69. else
  70. operator = OP_OVERLAP;
  71. }
  72. else if (parm.operator->answer[0] == 'r')
  73. operator = OP_RELATE;
  74. else
  75. G_fatal_error(_("Unknown operator '%s'"), parm.operator->answer);
  76. #ifdef HAVE_GEOS
  77. if (operator == OP_RELATE && !parm.relate->answer) {
  78. G_fatal_error(_("Required parameter <%s> not set"),
  79. parm.relate->key);
  80. }
  81. #else
  82. if (operator != OP_OVERLAP) {
  83. G_warning(_("Operator can only be 'overlap'"));
  84. operator = OP_OVERLAP;
  85. }
  86. #endif
  87. for (iopt = 0; iopt < 2; iopt++) {
  88. itype[iopt] = Vect_option_to_types(parm.type[iopt]);
  89. Vect_check_input_output_name(parm.input[iopt]->answer, parm.output->answer,
  90. G_FATAL_EXIT);
  91. Vect_set_open_level(2);
  92. if (Vect_open_old2(&(In[iopt]), parm.input[iopt]->answer, "",
  93. parm.field[iopt]->answer) < 0)
  94. G_fatal_error(_("Unable to open vector map <%s>"),
  95. parm.input[iopt]->answer);
  96. ifield[iopt] = Vect_get_field_number(&(In[iopt]), parm.field[iopt]->answer);
  97. }
  98. /* Alloc space for input lines array */
  99. nlines = Vect_get_num_lines(&(In[0]));
  100. nareas = Vect_get_num_areas(&(In[0]));
  101. ALines = (int *)G_calloc(nlines + 1, sizeof(int));
  102. AAreas = (int *)G_calloc(nareas + 1, sizeof(int));
  103. /* Read field info */
  104. IFi = Vect_get_field(&(In[0]), ifield[0]);
  105. /* Select features */
  106. #ifdef HAVE_GEOS
  107. nfound = select_lines(&(In[0]), itype[0], ifield[0],
  108. &(In[1]), itype[1], ifield[1],
  109. flag.cat->answer ? 1 : 0, operator,
  110. parm.relate->answer,
  111. ALines, AAreas, nskipped);
  112. #else
  113. nfound = select_lines(&(In[0]), itype[0], ifield[0],
  114. &(In[1]), itype[1], ifield[1],
  115. flag.cat->answer ? 1 : 0, operator,
  116. NULL,
  117. ALines, AAreas, nskipped);
  118. #endif
  119. #ifdef HAVE_GEOS
  120. finishGEOS();
  121. #endif
  122. if (!flag.reverse->answer) {
  123. G_free(AAreas);
  124. AAreas = NULL;
  125. }
  126. if ((!flag.reverse->answer && nfound > 0) ||
  127. (flag.reverse->answer && nlines + nareas - nfound > 0)) {
  128. /* Open output */
  129. if (Vect_open_new(&Out, parm.output->answer, Vect_is_3d(&(In[0]))) < 0)
  130. G_fatal_error(_("Unable to create vector map <%s>"),
  131. parm.output->answer);
  132. Vect_set_map_name(&Out, _("Output from v.select"));
  133. Vect_set_person(&Out, G_whoami());
  134. Vect_copy_head_data(&(In[0]), &Out);
  135. Vect_hist_copy(&(In[0]), &Out);
  136. Vect_hist_command(&Out);
  137. native = Vect_maptype(&Out) == GV_FORMAT_NATIVE;
  138. nfields = Vect_cidx_get_num_fields(&(In[0]));
  139. cats = (int **)G_malloc(nfields * sizeof(int *));
  140. ncats = (int *)G_malloc(nfields * sizeof(int));
  141. fields = (int *)G_malloc(nfields * sizeof(int));
  142. /* Write lines */
  143. if (!flag.table->answer && !native) {
  144. /* Copy attributes for OGR output */
  145. Vect_copy_map_dblinks(&(In[0]), &Out, TRUE);
  146. }
  147. write_lines(&(In[0]), IFi, ALines, AAreas,
  148. &Out, flag.table->answer ? 1 : 0, flag.reverse->answer ? 1 : 0,
  149. nfields, fields, ncats, cats);
  150. /* Copy tables */
  151. if (!flag.table->answer && native) {
  152. copy_tabs(&(In[0]), &Out,
  153. nfields, fields, ncats, cats);
  154. }
  155. /* print info about skipped features & close input maps */
  156. for (iopt = 0; iopt < 2; iopt++) {
  157. if (nskipped[iopt] > 0) {
  158. G_warning(_("%d features from <%s> without category skipped"),
  159. nskipped[iopt], Vect_get_full_name(&(In[iopt])));
  160. }
  161. Vect_set_release_support(&In[iopt]);
  162. Vect_close(&(In[iopt]));
  163. }
  164. Vect_build(&Out);
  165. nfound = Vect_get_num_lines(&Out);
  166. Vect_set_release_support(&Out);
  167. Vect_close(&Out);
  168. G_done_msg(_("%d features written to output."), nfound);
  169. }
  170. else {
  171. Vect_set_release_support(&In[0]);
  172. Vect_set_release_support(&In[1]);
  173. Vect_close(&In[0]);
  174. Vect_close(&In[1]);
  175. G_done_msg(_("No features found !"));
  176. }
  177. exit(EXIT_SUCCESS);
  178. }