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