main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /****************************************************************************
  2. *
  3. * MODULE: v.overlay
  4. * AUTHOR(S): Radim Blazek <radim.blazek gmail.com> (original contributor)
  5. * Glynn Clements <glynn gclements.plus.com>,
  6. * Hamish Bowman <hamish_b yahoo.com>,
  7. * Jachym Cepicky <jachym les-ejk.cz>,
  8. * Markus Neteler <neteler itc.it>,
  9. * Paul Kelly <paul-grass stjohnspoint.co.uk>
  10. * OGR support by Martin Landa <landa.martin gmail.com>
  11. * PURPOSE:
  12. * COPYRIGHT: (C) 2003-2009 by the GRASS Development Team
  13. *
  14. * This program is free software under the GNU General
  15. * Public License (>=v2). Read the file COPYING that
  16. * comes with GRASS for details.
  17. *
  18. *****************************************************************************/
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include <grass/gis.h>
  23. #include <grass/dbmi.h>
  24. #include <grass/vector.h>
  25. #include <grass/glocale.h>
  26. #include "local.h"
  27. int main(int argc, char *argv[])
  28. {
  29. int i, input, line, nlines, operator;
  30. int type[2], field[2], ofield[3];
  31. char *pre[2];
  32. struct GModule *module;
  33. struct Option *in_opt[2], *out_opt, *type_opt[2], *field_opt[2],
  34. *ofield_opt, *operator_opt;
  35. struct Flag *table_flag;
  36. struct Map_info In[2], Out;
  37. struct line_pnts *Points;
  38. struct line_cats *Cats;
  39. struct field_info *Fi = NULL;
  40. char buf[1000];
  41. dbString stmt;
  42. dbString sql, value_string, col_defs;
  43. dbDriver *driver;
  44. ATTRIBUTES attr[2];
  45. G_gisinit(argv[0]);
  46. pre[0] = "a";
  47. pre[1] = "b";
  48. module = G_define_module();
  49. G_add_keyword(_("vector"));
  50. G_add_keyword(_("geometry"));
  51. module->description = _("Overlays two vector maps.");
  52. in_opt[0] = G_define_standard_option(G_OPT_V_INPUT);
  53. in_opt[0]->label = _("Name of input vector map (A)");
  54. in_opt[0]->key = "ainput";
  55. field_opt[0] = G_define_standard_option(G_OPT_V_FIELD);
  56. field_opt[0]->label = _("Layer number or name (vector map A)");
  57. field_opt[0]->key = "alayer";
  58. type_opt[0] = G_define_standard_option(G_OPT_V_TYPE);
  59. type_opt[0]->label = _("Feature type (vector map A)");
  60. type_opt[0]->key = "atype";
  61. type_opt[0]->options = "line,area";
  62. type_opt[0]->answer = "area";
  63. in_opt[1] = G_define_standard_option(G_OPT_V_INPUT);
  64. in_opt[1]->label = _("Name of input vector map (B)");
  65. in_opt[1]->key = "binput";
  66. field_opt[1] = G_define_standard_option(G_OPT_V_FIELD);
  67. field_opt[1]->label = _("Layer number or name (vector map B)");
  68. field_opt[1]->key = "blayer";
  69. type_opt[1] = G_define_standard_option(G_OPT_V_TYPE);
  70. type_opt[1]->label = _("Feature type (vector map B)");
  71. type_opt[1]->key = "btype";
  72. type_opt[1]->options = "area";
  73. type_opt[1]->answer = "area";
  74. operator_opt = G_define_option();
  75. operator_opt->key = "operator";
  76. operator_opt->type = TYPE_STRING;
  77. operator_opt->required = YES;
  78. operator_opt->multiple = NO;
  79. operator_opt->options = "and,or,not,xor";
  80. operator_opt->label = _("Operator defines features written to "
  81. "output vector map");
  82. operator_opt->description =
  83. _("Feature is written to output if the result "
  84. "of operation 'ainput operator binput' is true. "
  85. "Input feature is considered to be true, if "
  86. "category of given layer is defined.");
  87. operator_opt->descriptions =
  88. _("and;also known as 'intersection' in GIS;"
  89. "or;also known as 'union' in GIS (only for atype=area);"
  90. "not;features from ainput not overlayed by features " "from binput;"
  91. "xor;features from either ainput or binput but "
  92. "not those from ainput overlayed by binput (only "
  93. "for atype=area)");
  94. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  95. ofield_opt = G_define_standard_option(G_OPT_V_FIELD);
  96. ofield_opt->key = "olayer";
  97. ofield_opt->multiple = YES;
  98. ofield_opt->answer = "1,0,0";
  99. ofield_opt->label = _("Output layer for new category, ainput and binput");
  100. ofield_opt->description = _("If 0 or not given, "
  101. "the category is not written");
  102. table_flag = G_define_flag();
  103. table_flag->key = 't';
  104. table_flag->description = _("Do not create attribute table");
  105. if (G_parser(argc, argv))
  106. exit(EXIT_FAILURE);
  107. for (input = 0; input < 2; input++) {
  108. type[input] = Vect_option_to_types(type_opt[input]);
  109. }
  110. ofield[0] = ofield[1] = ofield[2] = 0;
  111. i = 0;
  112. while (ofield_opt->answers[i] && i < 3) {
  113. ofield[i] = atoi(ofield_opt->answers[i]);
  114. i++;
  115. }
  116. if (operator_opt->answer[0] == 'a')
  117. operator = OP_AND;
  118. else if (operator_opt->answer[0] == 'o')
  119. operator = OP_OR;
  120. else if (operator_opt->answer[0] == 'n')
  121. operator = OP_NOT;
  122. else if (operator_opt->answer[0] == 'x')
  123. operator = OP_XOR;
  124. /* OP_OR, OP_XOR is not supported for lines,
  125. mostly because I'am not sure if they make enouhg sense */
  126. if (type[0] == GV_LINE && (operator == OP_OR || operator == OP_XOR))
  127. G_fatal_error(_("Operator '%s' is not supported for type line"),
  128. operator_opt->answer);
  129. Vect_check_input_output_name(in_opt[0]->answer, out_opt->answer,
  130. GV_FATAL_EXIT);
  131. Vect_check_input_output_name(in_opt[1]->answer, out_opt->answer,
  132. GV_FATAL_EXIT);
  133. Points = Vect_new_line_struct();
  134. Cats = Vect_new_cats_struct();
  135. /* Open output */
  136. Vect_open_new(&Out, out_opt->answer, WITHOUT_Z);
  137. Vect_set_map_name(&Out, "Output from v.overlay");
  138. Vect_set_person(&Out, G_whoami());
  139. Vect_hist_command(&Out);
  140. /* Create dblinks */
  141. if (ofield[0] > 0) {
  142. Fi = Vect_default_field_info(&Out, ofield[0], NULL, GV_1TABLE);
  143. }
  144. db_init_string(&sql);
  145. db_init_string(&value_string);
  146. db_init_string(&col_defs);
  147. /* Open database */
  148. if (ofield[0] > 0 && !(table_flag->answer)) {
  149. db_init_string(&stmt);
  150. driver =
  151. db_start_driver_open_database(Fi->driver,
  152. Vect_subst_var(Fi->database, &Out));
  153. if (driver == NULL) {
  154. Vect_close(&Out);
  155. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  156. Fi->database, Fi->driver);
  157. }
  158. db_begin_transaction(driver);
  159. }
  160. else {
  161. driver = NULL;
  162. }
  163. /* Copy lines to output */
  164. for (input = 0; input < 2; input++) {
  165. int ncats, index;
  166. Vect_set_open_level(2);
  167. Vect_open_old2(&(In[input]), in_opt[input]->answer, "", field_opt[input]->answer);
  168. field[input] = Vect_get_field_number(&(In[input]), field_opt[input]->answer);
  169. G_message(_("Copying vector features from <%s>..."),
  170. Vect_get_full_name(&(In[input])));
  171. nlines = Vect_get_num_lines(&(In[input]));
  172. for (line = 1; line <= nlines; line++) {
  173. int ltype;
  174. G_percent(line, nlines, 1); /* must be before any continue */
  175. ltype = Vect_read_line(&(In[input]), Points, Cats, line);
  176. if (type[input] == GV_AREA) {
  177. if (!(ltype & GV_BOUNDARY))
  178. continue;
  179. }
  180. else { /* GV_LINE */
  181. if (!(ltype & type[input]))
  182. continue;
  183. }
  184. Vect_write_line(&Out, ltype, Points, Cats);
  185. }
  186. /* Allocate attributes */
  187. attr[input].n = 0;
  188. /* this may be more than necessary */
  189. attr[input].attr =
  190. (ATTR *)
  191. G_calloc(Vect_cidx_get_type_count
  192. (&(In[input]), field[input], type[input]), sizeof(ATTR));
  193. index = Vect_cidx_get_field_index(&(In[input]), field[input]);
  194. if (index >= 0) {
  195. ncats = Vect_cidx_get_num_cats_by_index(&(In[input]), index);
  196. for (i = 0; i < ncats; i++) {
  197. int cat, ctype, id;
  198. Vect_cidx_get_cat_by_index(&(In[input]), index, i, &cat,
  199. &ctype, &id);
  200. if (!(ctype & type[input]))
  201. continue;
  202. if (attr[input].n == 0 ||
  203. cat != attr[input].attr[attr[input].n - 1].cat) {
  204. attr[input].attr[attr[input].n].cat = cat;
  205. attr[input].n++;
  206. }
  207. }
  208. }
  209. G_debug(3, "%d cats read from index", attr[input].n);
  210. G_verbose_message(_("Collecting input attributes..."));
  211. attr[input].null_values = NULL;
  212. attr[input].columns = NULL;
  213. /* Attributes */
  214. if (driver) {
  215. int ncol, more;
  216. struct field_info *inFi;
  217. dbDriver *in_driver;
  218. dbCursor cursor;
  219. dbTable *Table;
  220. dbColumn *Column;
  221. dbValue *Value;
  222. int sqltype, ctype;
  223. inFi = Vect_get_field(&(In[input]), field[input]);
  224. if (!inFi) {
  225. G_warning(_("Database connection not defined for layer %d"),
  226. field[input]);
  227. continue;
  228. }
  229. in_driver =
  230. db_start_driver_open_database(inFi->driver, inFi->database);
  231. if (in_driver == NULL) {
  232. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  233. inFi->database, inFi->driver);
  234. }
  235. sprintf(buf, "select * from %s", inFi->table);
  236. db_set_string(&sql, buf);
  237. if (db_open_select_cursor(in_driver, &sql, &cursor, DB_SEQUENTIAL)
  238. != DB_OK)
  239. G_fatal_error(_("Unable to select attributes"));
  240. Table = db_get_cursor_table(&cursor);
  241. ncol = db_get_table_number_of_columns(Table);
  242. G_debug(3, "ncol = %d", ncol);
  243. db_set_string(&sql, "");
  244. db_set_string(&col_defs, "");
  245. for (i = 0; i < ncol; i++) {
  246. db_append_string(&sql, ", null");
  247. Column = db_get_table_column(Table, i);
  248. sqltype = db_get_column_sqltype(Column);
  249. ctype = db_sqltype_to_Ctype(sqltype);
  250. if (input == 0)
  251. db_append_string(&col_defs, ", a_");
  252. else
  253. db_append_string(&col_defs, ", b_");
  254. db_append_string(&col_defs, db_get_column_name(Column));
  255. db_append_string(&col_defs, " ");
  256. switch (sqltype) {
  257. case DB_SQL_TYPE_CHARACTER:
  258. sprintf(buf, "varchar(%d)", db_get_column_length(Column));
  259. db_append_string(&col_defs, buf);
  260. break;
  261. case DB_SQL_TYPE_SMALLINT:
  262. case DB_SQL_TYPE_INTEGER:
  263. db_append_string(&col_defs, "integer");
  264. break;
  265. case DB_SQL_TYPE_REAL:
  266. case DB_SQL_TYPE_DOUBLE_PRECISION:
  267. case DB_SQL_TYPE_DECIMAL:
  268. case DB_SQL_TYPE_NUMERIC:
  269. case DB_SQL_TYPE_INTERVAL:
  270. db_append_string(&col_defs, "double precision");
  271. break;
  272. case DB_SQL_TYPE_DATE:
  273. db_append_string(&col_defs, "date");
  274. break;
  275. case DB_SQL_TYPE_TIME:
  276. db_append_string(&col_defs, "time");
  277. break;
  278. case DB_SQL_TYPE_TIMESTAMP:
  279. db_append_string(&col_defs, "datetime");
  280. break;
  281. default:
  282. G_warning(_("Unknown column type '%s'"),
  283. db_get_column_name(Column));
  284. sprintf(buf, "varchar(250)");
  285. }
  286. }
  287. attr[input].null_values = G_store(db_get_string(&sql));
  288. attr[input].columns = G_store(db_get_string(&col_defs));
  289. while (1) {
  290. int cat;
  291. ATTR *at;
  292. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK)
  293. G_fatal_error(_("Unable to fetch data from table"));
  294. if (!more)
  295. break;
  296. db_set_string(&sql, "");
  297. for (i = 0; i < ncol; i++) {
  298. Column = db_get_table_column(Table, i);
  299. sqltype = db_get_column_sqltype(Column);
  300. ctype = db_sqltype_to_Ctype(sqltype);
  301. Value = db_get_column_value(Column);
  302. if (G_strcasecmp(db_get_column_name(Column), inFi->key) ==
  303. 0) {
  304. cat = db_get_value_int(Value);
  305. G_debug(3, "cat = %d", cat);
  306. }
  307. db_append_string(&sql, ", ");
  308. db_convert_value_to_string(Value, sqltype, &value_string);
  309. G_debug(3, "%d: %s : %s", i, db_get_column_name(Column),
  310. db_get_string(&value_string));
  311. switch (ctype) {
  312. case DB_C_TYPE_STRING:
  313. case DB_C_TYPE_DATETIME:
  314. if (db_test_value_isnull(Value)) {
  315. db_append_string(&sql, "null");
  316. }
  317. else {
  318. db_double_quote_string(&value_string);
  319. sprintf(buf, "'%s'",
  320. db_get_string(&value_string));
  321. db_append_string(&sql, buf);
  322. }
  323. break;
  324. case DB_C_TYPE_INT:
  325. case DB_C_TYPE_DOUBLE:
  326. if (db_test_value_isnull(Value)) {
  327. db_append_string(&sql, "null");
  328. }
  329. else {
  330. db_append_string(&sql,
  331. db_get_string(&value_string));
  332. }
  333. break;
  334. default:
  335. G_warning(_("Unknown column type '%s' values lost"),
  336. db_get_column_name(Column));
  337. db_append_string(&sql, "null");
  338. }
  339. }
  340. at = find_attr(&(attr[input]), cat);
  341. if (!at)
  342. continue;
  343. /* if ( !at->used ) continue; *//* We don't know yet */
  344. at->values = G_store(db_get_string(&sql));
  345. G_debug(3, "values: %s", at->values);
  346. }
  347. db_table_to_sql(Table, &sql);
  348. db_close_database_shutdown_driver(in_driver);
  349. }
  350. }
  351. if (driver) {
  352. sprintf(buf, "create table %s (cat integer ", Fi->table);
  353. db_set_string(&stmt, buf);
  354. if (attr[0].columns)
  355. db_append_string(&stmt, attr[0].columns);
  356. else {
  357. sprintf(buf, ", a_cat integer");
  358. db_append_string(&stmt, buf);
  359. }
  360. if (attr[1].columns)
  361. db_append_string(&stmt, attr[1].columns);
  362. else {
  363. sprintf(buf, ", b_cat integer");
  364. db_append_string(&stmt, buf);
  365. }
  366. db_append_string(&stmt, " )");
  367. G_debug(3, db_get_string(&stmt));
  368. if (db_execute_immediate(driver, &stmt) != DB_OK) {
  369. Vect_close(&Out);
  370. db_close_database_shutdown_driver(driver);
  371. G_fatal_error(_("Unable to create table: '%s'"),
  372. db_get_string(&stmt));
  373. }
  374. if (db_create_index2(driver, Fi->table, "cat") != DB_OK)
  375. G_warning(_("Unable to create index"));
  376. if (db_grant_on_table
  377. (driver, Fi->table, DB_PRIV_SELECT,
  378. DB_GROUP | DB_PUBLIC) != DB_OK)
  379. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  380. Fi->table);
  381. /* Table created, now we can write dblink */
  382. Vect_map_add_dblink(&Out, ofield[0], NULL, Fi->table, "cat",
  383. Fi->database, Fi->driver);
  384. }
  385. G_verbose_message(_("Building partial topology..."));
  386. /* do not print output, because befor cleaning it is nonsense */
  387. Vect_build_partial(&Out, GV_BUILD_BASE);
  388. /* AREA x AREA */
  389. if (type[0] == GV_AREA) {
  390. area_area(In, field, &Out, Fi, driver, operator, ofield, attr);
  391. }
  392. else { /* LINE x AREA */
  393. line_area(In, field, &Out, Fi, driver, operator, ofield, attr);
  394. }
  395. G_message(_("Rebuilding topology..."));
  396. Vect_build_partial(&Out, GV_BUILD_NONE);
  397. Vect_build(&Out);
  398. /* Build topology to show the final result and prepare for Vect_close() */
  399. if (driver) {
  400. /* Close table */
  401. db_commit_transaction(driver);
  402. db_close_database_shutdown_driver(driver);
  403. }
  404. Vect_close(&(In[0]));
  405. Vect_close(&(In[1]));
  406. Vect_close(&Out);
  407. G_done_msg(" ");
  408. exit(EXIT_SUCCESS);
  409. }