main.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /****************************************************************************
  2. *
  3. * MODULE: r.to.vect
  4. *
  5. * AUTHOR(S): Bill Brown, Mike Baba, Jean Ezell and Andrew Heekin,
  6. * David Satnik, Andrea Aime, Radim Blazek
  7. *
  8. * PURPOSE: Converts a raster map into a vector map layer
  9. *
  10. * COPYRIGHT: (C) 2007, 2011 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <grass/gis.h>
  21. #include <grass/raster.h>
  22. #include <grass/dbmi.h>
  23. #include <grass/vector.h>
  24. #include <grass/glocale.h>
  25. #include "global.h"
  26. /*
  27. * Attributes for lines are ignored. For points and area by default unique new
  28. * category is assigned to each and raster value is written to 'value' column.
  29. * Labels are written to 'label' column if exists. If value flag (-v) is used
  30. * and type is CELL, raster values are used as categories.
  31. *
  32. * 2007/2: attributes for lines supported
  33. */
  34. int data_type;
  35. int data_size;
  36. struct Map_info Map;
  37. int input_fd; /* input raster map descriptor */
  38. struct line_cats *Cats;
  39. struct Cell_head cell_head;
  40. int direction;
  41. int first_read, last_read;
  42. int input_fd;
  43. int row_length, row_count, n_rows;
  44. int total_areas;
  45. int smooth_flag; /* this is 0 for no smoothing, 1 for smoothing of lines */
  46. int value_flag; /* use raster values as categories */
  47. struct Categories RastCats;
  48. int has_cats; /* Category labels available */
  49. struct field_info *Fi;
  50. dbDriver *driver;
  51. dbString sql, label;
  52. int main(int argc, char *argv[])
  53. {
  54. struct GModule *module;
  55. struct Option *in_opt, *out_opt, *feature_opt, *column_name;
  56. struct Flag *smooth_flg, *value_flg, *z_flg, *no_topol, *notab_flg;
  57. int feature, notab_flag;
  58. G_gisinit(argv[0]);
  59. module = G_define_module();
  60. G_add_keyword(_("raster"));
  61. G_add_keyword(_("conversion"));
  62. G_add_keyword(_("geometry"));
  63. G_add_keyword(_("vectorization"));
  64. module->description = _("Converts a raster map into a vector map.");
  65. in_opt = G_define_standard_option(G_OPT_R_INPUT);
  66. out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  67. feature_opt = G_define_standard_option(G_OPT_V_TYPE);
  68. feature_opt->description = _("Output feature type");
  69. feature_opt->required = YES;
  70. feature_opt->multiple = NO;
  71. feature_opt->options = "point,line,area";
  72. feature_opt->answer = NULL;
  73. column_name = G_define_standard_option(G_OPT_DB_COLUMN);
  74. column_name->label = _("Name of attribute column to store value");
  75. column_name->description = _("Name must be SQL compliant");
  76. column_name->answer = "value";
  77. smooth_flg = G_define_flag();
  78. smooth_flg->key = 's';
  79. smooth_flg->description = _("Smooth corners of area features");
  80. value_flg = G_define_flag();
  81. value_flg->key = 'v';
  82. value_flg->description =
  83. _("Use raster values as categories instead of unique sequence (CELL only)");
  84. value_flg->guisection = _("Attributes");
  85. z_flg = G_define_flag();
  86. z_flg->key = 'z';
  87. z_flg->label = _("Write raster values as z coordinate");
  88. z_flg->description = _("Table is not created. "
  89. "Currently supported only for points.");
  90. z_flg->guisection = _("Attributes");
  91. no_topol = G_define_flag();
  92. no_topol->key = 'b';
  93. no_topol->label = _("Do not build vector topology");
  94. no_topol->description = _("Recommended for massive point conversion");
  95. notab_flg = G_define_standard_flag(G_FLG_V_TABLE);
  96. if (G_parser(argc, argv))
  97. exit(EXIT_FAILURE);
  98. feature = Vect_option_to_types(feature_opt);
  99. smooth_flag = (smooth_flg->answer) ? SMOOTH : NO_SMOOTH;
  100. value_flag = value_flg->answer;
  101. notab_flag = notab_flg->answer;
  102. if (z_flg->answer && (feature != GV_POINT))
  103. G_fatal_error(_("z flag is supported only for points"));
  104. /* Open files */
  105. input_fd = Rast_open_old(in_opt->answer, "");
  106. data_type = Rast_get_map_type(input_fd);
  107. data_size = Rast_cell_size(data_type);
  108. G_get_window(&cell_head);
  109. if (value_flag && data_type != CELL_TYPE) {
  110. if (!notab_flag)
  111. G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table."));
  112. else if (z_flg->answer)
  113. G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be z coordinate."));
  114. else
  115. G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be lost."));
  116. value_flag = 0;
  117. }
  118. if (!value_flag && notab_flag) {
  119. G_warning(_("Categories will be unique sequence, raster values will be lost."));
  120. }
  121. if (z_flg->answer)
  122. Vect_open_new(&Map, out_opt->answer, 1);
  123. else
  124. Vect_open_new(&Map, out_opt->answer, 0);
  125. Vect_hist_command(&Map);
  126. Cats = Vect_new_cats_struct();
  127. /* Open category labels */
  128. if (data_type == CELL_TYPE) {
  129. if (0 == Rast_read_cats(in_opt->answer, "", &RastCats))
  130. has_cats = 1;
  131. }
  132. else
  133. has_cats = 0;
  134. db_init_string(&sql);
  135. db_init_string(&label);
  136. /* Create table */
  137. if ((feature & (GV_AREA | GV_POINT | GV_LINE)) &&
  138. (!value_flag || (value_flag && has_cats)) && !(z_flg->answer)
  139. && !notab_flag) {
  140. char buf[1000];
  141. Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);
  142. Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  143. Fi->driver);
  144. driver =
  145. db_start_driver_open_database(Fi->driver,
  146. Vect_subst_var(Fi->database, &Map));
  147. if (driver == NULL)
  148. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  149. Fi->database, Fi->driver);
  150. db_set_error_handler_driver(driver);
  151. /* Create new table */
  152. db_zero_string(&sql);
  153. sprintf(buf, "create table %s ( cat integer", Fi->table);
  154. db_append_string(&sql, buf);
  155. if (!value_flag) { /* add value to the table */
  156. if (data_type == CELL_TYPE) {
  157. db_append_string(&sql, ", ");
  158. db_append_string(&sql, column_name->answer);
  159. db_append_string(&sql, " integer");
  160. } else {
  161. db_append_string(&sql, ",");
  162. db_append_string(&sql, column_name->answer);
  163. db_append_string(&sql, " double precision");
  164. }
  165. }
  166. if (has_cats) {
  167. int i, len;
  168. int clen = 0;
  169. /* Get maximum column length */
  170. for (i = 0; i < RastCats.ncats; i++) {
  171. len = strlen(RastCats.labels[i]);
  172. if (len > clen)
  173. clen = len;
  174. }
  175. clen += 10;
  176. sprintf(buf, ", label varchar(%d)", clen);
  177. db_append_string(&sql, buf);
  178. }
  179. db_append_string(&sql, ")");
  180. G_debug(3, db_get_string(&sql));
  181. if (db_execute_immediate(driver, &sql) != DB_OK)
  182. G_fatal_error(_("Unable to create table: %s"),
  183. db_get_string(&sql));
  184. if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
  185. G_warning(_("Unable to create index"));
  186. if (db_grant_on_table
  187. (driver, Fi->table, DB_PRIV_SELECT,
  188. DB_GROUP | DB_PUBLIC) != DB_OK)
  189. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  190. Fi->table);
  191. db_begin_transaction(driver);
  192. }
  193. else {
  194. driver = NULL;
  195. }
  196. /* init variables for lines and areas */
  197. first_read = 1;
  198. last_read = 0;
  199. direction = FORWARD;
  200. row_length = cell_head.cols;
  201. n_rows = cell_head.rows;
  202. row_count = 0;
  203. if (feature == GV_LINE) {
  204. alloc_lines_bufs(row_length + 2);
  205. extract_lines();
  206. }
  207. else if (feature == GV_AREA) {
  208. alloc_areas_bufs(row_length + 2);
  209. extract_areas();
  210. }
  211. else { /* GV_POINT */
  212. extract_points(z_flg->answer);
  213. }
  214. Rast_close(input_fd);
  215. if (!no_topol->answer)
  216. Vect_build(&Map);
  217. /* insert cats and optionally labels if raster cats were used */
  218. if (driver && value_flag) {
  219. char buf[1000];
  220. int c, i, cat, fidx, ncats, lastcat, tp, id;
  221. fidx = Vect_cidx_get_field_index(&Map, 1);
  222. if (fidx >= 0) {
  223. ncats = Vect_cidx_get_num_cats_by_index(&Map, fidx);
  224. lastcat = -1;
  225. G_important_message(_("Updating attributes..."));
  226. for (c = 0; c < ncats; c++) {
  227. Vect_cidx_get_cat_by_index(&Map, fidx, c, &cat, &tp, &id);
  228. if (lastcat == cat)
  229. continue;
  230. /* find label, slow -> TODO faster */
  231. db_set_string(&label, "");
  232. for (i = 0; i < RastCats.ncats; i++) {
  233. if (cat == (int)RastCats.q.table[i].dLow) { /* cats are in dLow/High not in cLow/High !!! */
  234. db_set_string(&label, RastCats.labels[i]);
  235. db_double_quote_string(&label);
  236. break;
  237. }
  238. }
  239. G_debug(3, "cat = %d label = %s", cat, db_get_string(&label));
  240. sprintf(buf, "insert into %s values ( %d, '%s')", Fi->table,
  241. cat, db_get_string(&label));
  242. db_set_string(&sql, buf);
  243. G_debug(3, db_get_string(&sql));
  244. if (db_execute_immediate(driver, &sql) != DB_OK)
  245. G_fatal_error(_("Unable to insert into table: %s"),
  246. db_get_string(&sql));
  247. lastcat = cat;
  248. }
  249. }
  250. }
  251. if (has_cats)
  252. Rast_free_cats(&RastCats);
  253. if (driver != NULL) {
  254. db_commit_transaction(driver);
  255. db_close_database_shutdown_driver(driver);
  256. }
  257. Vect_close(&Map);
  258. G_done_msg(" ");
  259. exit(EXIT_SUCCESS);
  260. }