parse.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <grass/glocale.h>
  5. #include "global.h"
  6. int parse_units();
  7. int parse_option();
  8. int match();
  9. int parse_command_line(int argc, char *argv[])
  10. {
  11. int ncols;
  12. struct
  13. {
  14. struct Option *vect;
  15. struct Option *option;
  16. struct Option *type;
  17. struct Option *field;
  18. struct Option *qfield;
  19. struct Option *col;
  20. struct Option *units;
  21. struct Option *qcol;
  22. } parms;
  23. struct
  24. {
  25. struct Flag *p, *s, *t;
  26. } flags;
  27. parms.vect = G_define_standard_option(G_OPT_V_MAP);
  28. parms.field = G_define_standard_option(G_OPT_V_FIELD);
  29. parms.field->label = _("Layer number or name (write to)");
  30. parms.type = G_define_standard_option(G_OPT_V_TYPE);
  31. parms.type->options = "point,line,boundary,centroid";
  32. parms.type->answer = "point,line,boundary,centroid";
  33. parms.type->label = _("Feature type");
  34. parms.type->description =
  35. _("For coor valid point/centroid, "
  36. "for length valid line/boundary");
  37. parms.qfield = G_define_standard_option(G_OPT_V_FIELD);
  38. parms.qfield->key = "qlayer";
  39. parms.qfield->label = _("Query layer number or name (read from)");
  40. parms.qfield->guisection = _("Query");
  41. parms.option = G_define_option();
  42. parms.option->key = "option";
  43. parms.option->type = TYPE_STRING;
  44. parms.option->required = YES;
  45. parms.option->multiple = NO;
  46. parms.option->options =
  47. "cat,area,compact,fd,perimeter,length,count,coor,start,end,sides,query,slope,sinuous,azimuth";
  48. parms.option->description = _("Value to upload");
  49. parms.option->descriptions =
  50. "cat;insert new row for each category if doesn't exist yet;"
  51. "area;area size;"
  52. "compact;compactness of an area, calculated as \n"
  53. " compactness = perimeter / (2 * sqrt(PI * area));"
  54. "fd;fractal dimension of boundary defining a polygon, calculated as \n"
  55. " fd = 2 * (log(perimeter) / log(area));"
  56. "perimeter;perimeter length of an area;"
  57. "length;line length;"
  58. "count;number of features for each category;"
  59. "coor;point coordinates, X,Y or X,Y,Z;"
  60. "start;line/boundary starting point coordinates, X,Y or X,Y,Z;"
  61. "end;line/boundary end point coordinates, X,Y or X,Y,Z;"
  62. "sides;categories of areas on the left and right side of the boundary, "
  63. "'qlayer' is used for area category;"
  64. "query;result of a database query for all records of the geometry"
  65. "(or geometries) from table specified by 'qlayer' option;"
  66. "slope;slope steepness of vector line or boundary;"
  67. "sinuous;line sinuousity, calculated as line length / distance between end points;"
  68. "azimuth;line azimuth, calculated as angle between North direction and endnode direction at startnode";
  69. parms.units = G_define_option();
  70. parms.units->key = "units";
  71. parms.units->type = TYPE_STRING;
  72. parms.units->required = NO;
  73. parms.units->multiple = NO;
  74. parms.units->options =
  75. "miles,feet,meters,kilometers,acres,hectares,radians,degrees";
  76. parms.units->label = _("Units");
  77. parms.units->description =
  78. _("miles,feet,meters,kilometers,acres,hectares,radians,degrees");
  79. parms.col = G_define_standard_option(G_OPT_DB_COLUMNS);
  80. parms.qcol = G_define_standard_option(G_OPT_DB_COLUMN);
  81. parms.qcol->key = "qcolumn";
  82. parms.qcol->label = _("Name of attribute column used for 'query' option");
  83. parms.qcol->description = _("E.g. 'cat', 'count(*)', 'sum(val)'");
  84. parms.qcol->required = NO;
  85. parms.qcol->guisection = _("Query");
  86. flags.p = G_define_flag();
  87. flags.p->key = 'p';
  88. flags.p->description = _("Print only");
  89. flags.p->guisection = _("Print");
  90. flags.s = G_define_flag();
  91. flags.s->key = 's';
  92. flags.s->description = _("Only print SQL statements");
  93. flags.s->guisection = _("Print");
  94. flags.t = G_define_flag();
  95. flags.t->key = 'c';
  96. flags.t->description =
  97. _("In print mode prints totals for options: length,area,count");
  98. flags.t->guisection = _("Print");
  99. if (G_parser(argc, argv))
  100. exit(EXIT_FAILURE);
  101. options.print = flags.p->answer;
  102. options.sql = flags.s->answer;
  103. options.total = flags.t->answer;
  104. options.name = parms.vect->answer;
  105. options.type = Vect_option_to_types(parms.type);
  106. options.field = atoi(parms.field->answer);
  107. options.qfield = atoi(parms.qfield->answer);
  108. options.option = parse_option(parms.option->answer);
  109. options.units = parse_units(parms.units->answer);
  110. /* Check number of columns */
  111. ncols = 0;
  112. options.col[0] = NULL;
  113. options.col[1] = NULL;
  114. options.col[2] = NULL;
  115. while (parms.col->answers && parms.col->answers[ncols]) {
  116. options.col[ncols] = G_store(parms.col->answers[ncols]);
  117. ncols++;
  118. }
  119. if (!options.print) {
  120. if (options.option == O_AREA || options.option == O_LENGTH || options.option == O_COUNT || options.option == O_QUERY || options.option == O_COMPACT || options.option == O_FD || options.option == O_PERIMETER || options.option == O_SLOPE || options.option == O_SINUOUS || options.option == O_AZIMUTH) { /* one column required */
  121. if (ncols != 1) {
  122. G_fatal_error(_("This option requires one column"));
  123. }
  124. }
  125. else if (options.option == O_SIDES) {
  126. if (ncols != 2) {
  127. G_fatal_error(_("This option requires two columns"));
  128. }
  129. }
  130. else if (options.option == O_COOR) {
  131. if (ncols < 2) {
  132. G_fatal_error(_("This option requires at least two columns"));
  133. }
  134. }
  135. }
  136. if (options.option == O_QUERY && !parms.qcol->answers)
  137. G_fatal_error(_("Parameter 'qcolumn' must be specified for 'option=query'"));
  138. options.qcol = parms.qcol->answer;
  139. if (options.option == O_SIDES && !(options.type | GV_BOUNDARY))
  140. G_fatal_error(_("The 'sides' option makes sense only for boundaries"));
  141. if (options.option == O_SINUOUS && !(options.type | GV_LINES))
  142. G_fatal_error(_("The 'sinuous' option makes sense only for lines"));
  143. if (options.option == O_AZIMUTH && !(options.type | GV_LINES))
  144. G_fatal_error(_("The 'azimuth' option makes sense only for lines"));
  145. return 0;
  146. }
  147. int parse_units(char *s)
  148. {
  149. int x = 0;
  150. if (match(s, "miles", 2))
  151. x = U_MILES;
  152. else if (match(s, "feet", 1))
  153. x = U_FEET;
  154. else if (match(s, "meters", 2))
  155. x = U_METERS;
  156. else if (match(s, "kilometers", 1))
  157. x = U_KILOMETERS;
  158. else if (match(s, "acres", 1))
  159. x = U_ACRES;
  160. else if (match(s, "hectares", 1))
  161. x = U_HECTARES;
  162. else if (match(s, "radians", 1))
  163. x = U_RADIANS;
  164. else if (match(s, "degrees", 1))
  165. x = U_DEGREES;
  166. return x;
  167. }
  168. int parse_option(char *s)
  169. {
  170. int x = 0;
  171. if (strcmp(s, "cat") == 0)
  172. x = O_CAT;
  173. else if (strcmp(s, "area") == 0)
  174. x = O_AREA;
  175. else if (strcmp(s, "length") == 0)
  176. x = O_LENGTH;
  177. else if (strcmp(s, "count") == 0)
  178. x = O_COUNT;
  179. else if (strcmp(s, "coor") == 0)
  180. x = O_COOR;
  181. else if (strcmp(s, "start") == 0)
  182. x = O_START;
  183. else if (strcmp(s, "end") == 0)
  184. x = O_END;
  185. else if (strcmp(s, "sides") == 0)
  186. x = O_SIDES;
  187. else if (strcmp(s, "query") == 0)
  188. x = O_QUERY;
  189. else if (strcmp(s, "compact") == 0)
  190. x = O_COMPACT;
  191. else if (strcmp(s, "fd") == 0)
  192. x = O_FD;
  193. else if (strcmp(s, "perimeter") == 0)
  194. x = O_PERIMETER;
  195. else if (strcmp(s, "slope") == 0)
  196. x = O_SLOPE;
  197. else if (strcmp(s, "sinuous") == 0)
  198. x = O_SINUOUS;
  199. else if (strcmp(s, "azimuth") == 0)
  200. x = O_AZIMUTH;
  201. return x;
  202. }
  203. int match(char *s, char *key, int min)
  204. {
  205. size_t len;
  206. if (!s)
  207. return 0;
  208. len = strlen(s);
  209. if (len < (size_t) min)
  210. return 0;
  211. return strncmp(s, key, len) == 0;
  212. }