write_ogr.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*!
  2. \file vector/Vlib/write_ogr.c
  3. \brief Vector library - write vector feature (OGR format)
  4. Higher level functions for reading/writing/manipulating vectors.
  5. Inspired by v.out.ogr's code.
  6. (C) 2009-2010 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. \author Martin Landa <landa.martin gmail.com>
  10. */
  11. #include <grass/config.h>
  12. #include <grass/vector.h>
  13. #include <grass/dbmi.h>
  14. #include <grass/glocale.h>
  15. #ifdef HAVE_OGR
  16. #include <ogr_api.h>
  17. static int write_attributes(int, const struct field_info *,
  18. OGRLayerH, OGRFeatureH);
  19. /*!
  20. \brief Writes feature on level 1
  21. \param Map pointer to Map_info structure
  22. \param type feature type
  23. \param points pointer to line_pnts structure (feature geometry)
  24. \param cats pointer to line_cats structure (feature categories)
  25. \return feature offset into file
  26. \return -1 on error
  27. */
  28. off_t V1_write_line_ogr(struct Map_info *Map,
  29. int type, const struct line_pnts *points, const struct line_cats *cats)
  30. {
  31. int i, cat, ret;
  32. struct field_info *Fi;
  33. OGRGeometryH Ogr_geometry;
  34. OGRFeatureH Ogr_feature;
  35. OGRFeatureDefnH Ogr_featuredefn;
  36. if (!Map->fInfo.ogr.layer) {
  37. G_warning(_("OGR layer not defined"));
  38. return -1;
  39. }
  40. /* determine feature's geometry */
  41. if (type & (GV_POINTS | GV_KERNEL)) {
  42. Ogr_geometry = OGR_G_CreateGeometry(wkbPoint);
  43. }
  44. else if (type & GV_LINES) {
  45. Ogr_geometry = OGR_G_CreateGeometry(wkbLineString);
  46. }
  47. else if (type & GV_FACE) {
  48. Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon25D);
  49. }
  50. else {
  51. G_warning("V1_write_line_ogr(): %s (%d)", _("Unsupported feature type"), type);
  52. return -1;
  53. }
  54. G_debug(3, "V1_write_line_ogr(): type = %d", type);
  55. for (i = 0; i < points->n_points; i++) {
  56. OGR_G_AddPoint(Ogr_geometry, points->x[i], points->y[i],
  57. points->z[i]);
  58. }
  59. G_debug(4, " n_points = %d", points->n_points);
  60. Ogr_featuredefn = OGR_L_GetLayerDefn(Map->fInfo.ogr.layer);
  61. /* create feature & set geometry */
  62. Ogr_feature = OGR_F_Create(Ogr_featuredefn);
  63. OGR_F_SetGeometry(Ogr_feature, Ogr_geometry);
  64. /* write attributes */
  65. if (cats->n_cats > 0) {
  66. cat = cats->cat[0];
  67. if (cats->n_cats > 1) {
  68. G_warning(_("Feature has more categories, using "
  69. "category %d (from layer %d)"),
  70. cat, cats->field[0]);
  71. }
  72. Fi = Vect_get_field(Map, cats->field[0]);
  73. if (!Fi) {
  74. G_fatal_error(_("Database connection not defined for layer %d"),
  75. cats->field[0]);
  76. }
  77. write_attributes(cat, Fi, Map->fInfo.ogr.layer, Ogr_feature);
  78. }
  79. else { /* no attributes */
  80. G_warning(_("Feature has no categories"));
  81. }
  82. /* write feature into layer */
  83. ret = OGR_L_CreateFeature(Map->fInfo.ogr.layer, Ogr_feature);
  84. /* destroy */
  85. OGR_G_DestroyGeometry(Ogr_geometry);
  86. OGR_F_Destroy(Ogr_feature);
  87. if (ret != OGRERR_NONE)
  88. return -1;
  89. return Map->fInfo.ogr.offset_num++;
  90. }
  91. /*!
  92. \brief Writes feature (topology level)
  93. \param Map pointer to Map_info structure
  94. \param type feature type
  95. \param points feature geometry
  96. \param cats feature categories
  97. \return new feature id
  98. \return -1 on error
  99. */
  100. off_t V2_write_line_ogr(struct Map_info *Map,
  101. int type, const struct line_pnts *points, const struct line_cats *cats)
  102. {
  103. return V2__write_line(Map, type, points, cats, V1_write_line_ogr);
  104. }
  105. /*!
  106. \brief Deletes feature at the given offset (level 1)
  107. \param Map pointer Map_info structure
  108. \param offset feature offset
  109. \return 0 on success
  110. \return -1 on error
  111. */
  112. int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
  113. {
  114. G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
  115. if (!Map->fInfo.ogr.layer) {
  116. G_warning(_("OGR layer not defined"));
  117. return -1;
  118. }
  119. if (offset >= Map->fInfo.ogr.offset_num)
  120. return -1;
  121. if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer, Map->fInfo.ogr.offset[offset]) != OGRERR_NONE)
  122. return -1;
  123. return 0;
  124. }
  125. /*!
  126. \brief Deletes feature (topology level).
  127. \param Map pointer to Map_info structure
  128. \param line feature id
  129. \return 0 on success
  130. \return -1 on error
  131. */
  132. int V2_delete_line_ogr(struct Map_info *Map, int line)
  133. {
  134. return V2__delete_line(Map, line, V1_delete_line_ogr);
  135. }
  136. /*!
  137. \brief Rewrites feature at the given offset (level 1)
  138. \param Map pointer to Map_info structure
  139. \param offset feature offset
  140. \param type feature type
  141. \param points feature geometry
  142. \param cats feature categories
  143. \return feature offset (rewriten feature)
  144. \return -1 on error
  145. */
  146. off_t V1_rewrite_line_ogr(struct Map_info *Map,
  147. off_t offset,
  148. int type,
  149. const struct line_pnts *points, const struct line_cats *cats)
  150. {
  151. if (type != V1_read_line_ogr(Map, NULL, NULL, offset)) {
  152. G_warning(_("Unable to rewrite feature (incompatible feature types)"));
  153. return -1;
  154. }
  155. /* delete old */
  156. V1_delete_line_ogr(Map, offset);
  157. return V1_write_line_ogr(Map, type, points, cats);
  158. }
  159. /*!
  160. \brief Rewrites feature (topology level)
  161. \param Map pointer to Map_info structure
  162. \param line feature id
  163. \param type feature type
  164. \param points feature geometry
  165. \param cats feature categories
  166. \return feature offset (rewriten feature)
  167. \return -1 on error
  168. */
  169. int V2_rewrite_line_ogr(struct Map_info *Map,
  170. int line,
  171. int type,
  172. const struct line_pnts *points, const struct line_cats *cats)
  173. {
  174. /* delete old */
  175. V2_delete_line_ogr(Map, line);
  176. return V2_write_line_ogr(Map, type, points, cats);
  177. }
  178. int write_attributes(int cat, const struct field_info *Fi,
  179. OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
  180. {
  181. int j, ogrfieldnum;
  182. char buf[2000];
  183. int ncol, colsqltype, colctype, more;
  184. const char *fidcol;
  185. dbDriver *Driver;
  186. dbTable *Table;
  187. dbString dbstring;
  188. dbColumn *Column;
  189. dbCursor cursor;
  190. dbValue *Value;
  191. G_debug(3, "write_attributes(): cat = %d", cat);
  192. if (cat < 0) {
  193. G_warning ("Feature without category of layer %d", Fi->number);
  194. return 0;
  195. }
  196. db_init_string(&dbstring);
  197. /* read & set attributes */
  198. sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key,
  199. cat);
  200. G_debug(4, "SQL: %s", buf);
  201. db_set_string(&dbstring, buf);
  202. /* open driver & select data */
  203. Driver = db_start_driver_open_database(Fi->driver, Fi->database);
  204. if (!Driver)
  205. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  206. Fi->database, Fi->driver);
  207. if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
  208. G_fatal_error(_("Unable to select attributes for category %d"),
  209. cat);
  210. }
  211. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
  212. G_fatal_error(_("Unable to fetch data from table <%s>"),
  213. Fi->table);
  214. }
  215. if (!more) {
  216. G_warning (_("No database record for category %d - export of 'cat' disabled"),
  217. cat);
  218. return -1;
  219. }
  220. fidcol = OGR_L_GetFIDColumn(Ogr_layer);
  221. Table = db_get_cursor_table(&cursor);
  222. ncol = db_get_table_number_of_columns(Table);
  223. for (j = 0; j < ncol; j++) {
  224. Column = db_get_table_column(Table, j);
  225. if (fidcol && strcmp(db_get_column_name(Column), fidcol) == 0) {
  226. /* skip fid column */
  227. continue;
  228. }
  229. Value = db_get_column_value(Column);
  230. db_convert_column_value_to_string(Column, &dbstring); /* for debug only */
  231. G_debug(2, "col %d : val = %s", j,
  232. db_get_string(&dbstring));
  233. colsqltype = db_get_column_sqltype(Column);
  234. colctype = db_sqltype_to_Ctype(colsqltype);
  235. G_debug(2, " colctype = %d", colctype);
  236. ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature,
  237. db_get_column_name(Column));
  238. if (ogrfieldnum < 0) {
  239. G_warning(_("Uknown column <%s>"),
  240. db_get_column_name(Column));
  241. continue;
  242. }
  243. /* Reset */
  244. OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
  245. /* prevent writing NULL values */
  246. if (!db_test_value_isnull(Value)) {
  247. switch (colctype) {
  248. case DB_C_TYPE_INT:
  249. OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
  250. db_get_value_int(Value));
  251. break;
  252. case DB_C_TYPE_DOUBLE:
  253. OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
  254. db_get_value_double(Value));
  255. break;
  256. case DB_C_TYPE_STRING:
  257. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  258. db_get_value_string(Value));
  259. break;
  260. case DB_C_TYPE_DATETIME:
  261. db_convert_column_value_to_string(Column,
  262. &dbstring);
  263. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  264. db_get_string(&dbstring));
  265. break;
  266. }
  267. }
  268. }
  269. db_close_cursor (&cursor);
  270. db_close_database(Driver);
  271. db_shutdown_driver(Driver);
  272. db_free_string(&dbstring);
  273. return 1;
  274. }
  275. #endif /* HAVE_OGR */