main.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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;
  57. int feature;
  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->required = YES;
  69. feature_opt->multiple = NO;
  70. feature_opt->options = "point,line,area";
  71. feature_opt->answer = NULL;
  72. column_name = G_define_standard_option(G_OPT_DB_COLUMN);
  73. column_name->label = _("Name of attribute column to store value");
  74. column_name->description = _("Name must be SQL compliant");
  75. column_name->answer = "value";
  76. smooth_flg = G_define_flag();
  77. smooth_flg->key = 's';
  78. smooth_flg->description = _("Smooth corners of area features");
  79. value_flg = G_define_flag();
  80. value_flg->key = 'v';
  81. value_flg->description =
  82. _("Use raster values as categories instead of unique sequence (CELL only)");
  83. value_flg->guisection = _("Attributes");
  84. z_flg = G_define_flag();
  85. z_flg->key = 'z';
  86. z_flg->label = _("Write raster values as z coordinate");
  87. z_flg->description = _("Table is not created. "
  88. "Currently supported only for points.");
  89. z_flg->guisection = _("Attributes");
  90. no_topol = G_define_flag();
  91. no_topol->key = 'b';
  92. no_topol->label = _("Do not build vector topology");
  93. no_topol->description = _("Recommended for massive point conversion");
  94. if (G_parser(argc, argv))
  95. exit(EXIT_FAILURE);
  96. feature = Vect_option_to_types(feature_opt);
  97. smooth_flag = (smooth_flg->answer) ? SMOOTH : NO_SMOOTH;
  98. value_flag = value_flg->answer;
  99. if (z_flg->answer && (feature != GV_POINT))
  100. G_fatal_error(_("z flag is supported only for points"));
  101. /* Open files */
  102. input_fd = Rast_open_old(in_opt->answer, "");
  103. data_type = Rast_get_map_type(input_fd);
  104. data_size = Rast_cell_size(data_type);
  105. G_get_window(&cell_head);
  106. if (value_flag && data_type != CELL_TYPE) {
  107. G_warning(_("Raster is not CELL, '-v' flag ignored, raster values will be written to the table."));
  108. value_flag = 0;
  109. }
  110. if (z_flg->answer)
  111. Vect_open_new(&Map, out_opt->answer, 1);
  112. else
  113. Vect_open_new(&Map, out_opt->answer, 0);
  114. Vect_hist_command(&Map);
  115. Cats = Vect_new_cats_struct();
  116. /* Open category labels */
  117. if (data_type == CELL_TYPE) {
  118. if (0 == Rast_read_cats(in_opt->answer, "", &RastCats))
  119. has_cats = 1;
  120. }
  121. else
  122. has_cats = 0;
  123. db_init_string(&sql);
  124. db_init_string(&label);
  125. /* Create table */
  126. if ((feature & (GV_AREA | GV_POINT | GV_LINE)) &&
  127. (!value_flag || (value_flag && has_cats)) && !(z_flg->answer)) {
  128. char buf[1000];
  129. Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);
  130. Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
  131. Fi->driver);
  132. driver =
  133. db_start_driver_open_database(Fi->driver,
  134. Vect_subst_var(Fi->database, &Map));
  135. if (driver == NULL)
  136. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  137. Fi->database, Fi->driver);
  138. /* Create new table */
  139. db_zero_string(&sql);
  140. sprintf(buf, "create table %s ( cat integer", Fi->table);
  141. db_append_string(&sql, buf);
  142. if (!value_flag) { /* add value to the table */
  143. if (data_type == CELL_TYPE) {
  144. db_append_string(&sql, ", ");
  145. db_append_string(&sql, column_name->answer);
  146. db_append_string(&sql, " integer");
  147. } else {
  148. db_append_string(&sql, ",");
  149. db_append_string(&sql, column_name->answer);
  150. db_append_string(&sql, " double precision");
  151. }
  152. }
  153. if (has_cats) {
  154. int i, len;
  155. int clen = 0;
  156. /* Get maximum column length */
  157. for (i = 0; i < RastCats.ncats; i++) {
  158. len = strlen(RastCats.labels[i]);
  159. if (len > clen)
  160. clen = len;
  161. }
  162. clen += 10;
  163. sprintf(buf, ", label varchar(%d)", clen);
  164. db_append_string(&sql, buf);
  165. }
  166. db_append_string(&sql, ")");
  167. G_debug(3, db_get_string(&sql));
  168. if (db_execute_immediate(driver, &sql) != DB_OK)
  169. G_fatal_error(_("Unable to create table: %s"),
  170. db_get_string(&sql));
  171. if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
  172. G_warning(_("Unable to create index"));
  173. if (db_grant_on_table
  174. (driver, Fi->table, DB_PRIV_SELECT,
  175. DB_GROUP | DB_PUBLIC) != DB_OK)
  176. G_fatal_error(_("Unable to grant privileges on table <%s>"),
  177. Fi->table);
  178. db_begin_transaction(driver);
  179. }
  180. else {
  181. driver = NULL;
  182. }
  183. /* init variables for lines and areas */
  184. first_read = 1;
  185. last_read = 0;
  186. direction = FORWARD;
  187. row_length = cell_head.cols;
  188. n_rows = cell_head.rows;
  189. row_count = 0;
  190. if (feature == GV_LINE) {
  191. alloc_lines_bufs(row_length + 2);
  192. extract_lines();
  193. }
  194. else if (feature == GV_AREA) {
  195. alloc_areas_bufs(row_length + 2);
  196. extract_areas();
  197. }
  198. else { /* GV_POINT */
  199. extract_points(z_flg->answer);
  200. }
  201. Rast_close(input_fd);
  202. if (!no_topol->answer)
  203. Vect_build(&Map);
  204. /* insert cats and optionally labels if raster cats were used */
  205. if (driver && value_flag) {
  206. char buf[1000];
  207. int c, i, cat, fidx, ncats, lastcat, tp, id;
  208. fidx = Vect_cidx_get_field_index(&Map, 1);
  209. if (fidx >= 0) {
  210. ncats = Vect_cidx_get_num_cats_by_index(&Map, fidx);
  211. lastcat = -1;
  212. G_important_message(_("Updating attributes..."));
  213. for (c = 0; c < ncats; c++) {
  214. Vect_cidx_get_cat_by_index(&Map, fidx, c, &cat, &tp, &id);
  215. if (lastcat == cat)
  216. continue;
  217. /* find label, slow -> TODO faster */
  218. db_set_string(&label, "");
  219. for (i = 0; i < RastCats.ncats; i++) {
  220. if (cat == (int)RastCats.q.table[i].dLow) { /* cats are in dLow/High not in cLow/High !!! */
  221. db_set_string(&label, RastCats.labels[i]);
  222. db_double_quote_string(&label);
  223. break;
  224. }
  225. }
  226. G_debug(3, "cat = %d label = %s", cat, db_get_string(&label));
  227. sprintf(buf, "insert into %s values ( %d, '%s')", Fi->table,
  228. cat, db_get_string(&label));
  229. db_set_string(&sql, buf);
  230. G_debug(3, db_get_string(&sql));
  231. if (db_execute_immediate(driver, &sql) != DB_OK)
  232. G_fatal_error(_("Unable to insert into table: %s"),
  233. db_get_string(&sql));
  234. lastcat = cat;
  235. }
  236. }
  237. }
  238. if (has_cats)
  239. Rast_free_cats(&RastCats);
  240. if (driver != NULL) {
  241. db_commit_transaction(driver);
  242. db_close_database_shutdown_driver(driver);
  243. }
  244. Vect_close(&Map);
  245. G_done_msg(" ");
  246. exit(EXIT_SUCCESS);
  247. }