write_ogr.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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 (OGR format)
  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 to 'coor' file (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. int write_attributes(int cat, const struct field_info *Fi,
  137. OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature)
  138. {
  139. int j, ogrfieldnum;
  140. char buf[2000];
  141. int ncol, colsqltype, colctype, more;
  142. char *fidcol;
  143. dbDriver *Driver;
  144. dbTable *Table;
  145. dbString dbstring;
  146. dbColumn *Column;
  147. dbCursor cursor;
  148. dbValue *Value;
  149. G_debug(3, "write_attributes(): cat = %d", cat);
  150. if (cat < 0) {
  151. G_warning ("Feature without category of layer %d", Fi->number);
  152. return 0;
  153. }
  154. db_init_string(&dbstring);
  155. /* read & set attributes */
  156. sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key,
  157. cat);
  158. G_debug(4, "SQL: %s", buf);
  159. db_set_string(&dbstring, buf);
  160. /* open driver & select data */
  161. Driver = db_start_driver_open_database(Fi->driver, Fi->database);
  162. if (!Driver)
  163. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  164. Fi->database, Fi->driver);
  165. if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
  166. G_fatal_error(_("Unable to select attributes for category %d"),
  167. cat);
  168. }
  169. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
  170. G_fatal_error(_("Unable to fetch data from table <%s>"),
  171. Fi->table);
  172. }
  173. if (!more) {
  174. G_warning (_("No database record for category %d - export of 'cat' disabled"),
  175. cat);
  176. return -1;
  177. }
  178. fidcol = OGR_L_GetFIDColumn(Ogr_layer);
  179. Table = db_get_cursor_table(&cursor);
  180. ncol = db_get_table_number_of_columns(Table);
  181. for (j = 0; j < ncol; j++) {
  182. Column = db_get_table_column(Table, j);
  183. if (fidcol && strcmp(db_get_column_name(Column), fidcol) == 0) {
  184. /* skip fid column */
  185. continue;
  186. }
  187. Value = db_get_column_value(Column);
  188. db_convert_column_value_to_string(Column, &dbstring); /* for debug only */
  189. G_debug(2, "col %d : val = %s", j,
  190. db_get_string(&dbstring));
  191. colsqltype = db_get_column_sqltype(Column);
  192. colctype = db_sqltype_to_Ctype(colsqltype);
  193. G_debug(2, " colctype = %d", colctype);
  194. ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature,
  195. db_get_column_name(Column));
  196. if (ogrfieldnum < 0) {
  197. G_warning(_("Uknown column <%s>"),
  198. db_get_column_name(Column));
  199. continue;
  200. }
  201. /* Reset */
  202. OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
  203. /* prevent writing NULL values */
  204. if (!db_test_value_isnull(Value)) {
  205. switch (colctype) {
  206. case DB_C_TYPE_INT:
  207. OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
  208. db_get_value_int(Value));
  209. break;
  210. case DB_C_TYPE_DOUBLE:
  211. OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
  212. db_get_value_double(Value));
  213. break;
  214. case DB_C_TYPE_STRING:
  215. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  216. db_get_value_string(Value));
  217. break;
  218. case DB_C_TYPE_DATETIME:
  219. db_convert_column_value_to_string(Column,
  220. &dbstring);
  221. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  222. db_get_string(&dbstring));
  223. break;
  224. }
  225. }
  226. }
  227. db_close_cursor (&cursor);
  228. db_close_database(Driver);
  229. db_shutdown_driver(Driver);
  230. db_free_string(&dbstring);
  231. return 1;
  232. }
  233. #endif /* HAVE_OGR */