write_ogr.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. 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 0 on success
  26. \return -1 on error
  27. */
  28. int 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;
  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, Ogr_feature);
  78. }
  79. else { /* no attributes */
  80. G_warning(_("Feature has no categories"));
  81. }
  82. /* write feature into layer */
  83. OGR_L_CreateFeature(Map->fInfo.ogr.layer, Ogr_feature);
  84. /* destroy */
  85. OGR_G_DestroyGeometry(Ogr_geometry);
  86. OGR_F_Destroy(Ogr_feature);
  87. return 0;
  88. }
  89. int write_attributes(int cat, const struct field_info *Fi,
  90. OGRFeatureH Ogr_feature)
  91. {
  92. int j, ogrfieldnum;
  93. char buf[2000];
  94. int ncol, colsqltype, colctype, more;
  95. dbDriver *Driver;
  96. dbTable *Table;
  97. dbString dbstring;
  98. dbColumn *Column;
  99. dbCursor cursor;
  100. dbValue *Value;
  101. G_debug(3, "write_attributes(): cat = %d", cat);
  102. if (cat < 0) {
  103. G_warning ("Feature without category of layer %d", Fi->number);
  104. return 0;
  105. }
  106. db_init_string(&dbstring);
  107. /* read & set attributes */
  108. sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key,
  109. cat);
  110. G_debug(4, "SQL: %s", buf);
  111. db_set_string(&dbstring, buf);
  112. /* open driver & select data */
  113. Driver = db_start_driver(Fi->driver);
  114. if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) {
  115. G_fatal_error(_("Unable to select attributes for category %d"),
  116. cat);
  117. }
  118. if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
  119. G_fatal_error(_("Unable to fetch data from table <%s>"),
  120. Fi->table);
  121. }
  122. if (!more) {
  123. G_warning (_("No database record for category %d - export of 'cat' disabled"),
  124. cat);
  125. return -1;
  126. }
  127. Table = db_get_cursor_table(&cursor);
  128. ncol = db_get_table_number_of_columns(Table);
  129. for (j = 0; j < ncol; j++) {
  130. Column = db_get_table_column(Table, j);
  131. Value = db_get_column_value(Column);
  132. db_convert_column_value_to_string(Column, &dbstring); /* for debug only */
  133. G_debug(2, "col %d : val = %s", j,
  134. db_get_string(&dbstring));
  135. colsqltype = db_get_column_sqltype(Column);
  136. colctype = db_sqltype_to_Ctype(colsqltype);
  137. G_debug(2, " colctype = %d", colctype);
  138. ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature,
  139. db_get_column_name(Column));
  140. /* Reset */
  141. OGR_F_UnsetField(Ogr_feature, ogrfieldnum);
  142. /* prevent writing NULL values */
  143. if (!db_test_value_isnull(Value)) {
  144. switch (colctype) {
  145. case DB_C_TYPE_INT:
  146. OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum,
  147. db_get_value_int(Value));
  148. break;
  149. case DB_C_TYPE_DOUBLE:
  150. OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum,
  151. db_get_value_double(Value));
  152. break;
  153. case DB_C_TYPE_STRING:
  154. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  155. db_get_value_string(Value));
  156. break;
  157. case DB_C_TYPE_DATETIME:
  158. db_convert_column_value_to_string(Column,
  159. &dbstring);
  160. OGR_F_SetFieldString(Ogr_feature, ogrfieldnum,
  161. db_get_string(&dbstring));
  162. break;
  163. }
  164. }
  165. }
  166. db_close_cursor (&cursor);
  167. db_close_database(Driver);
  168. db_shutdown_driver(Driver);
  169. db_free_string(&dbstring);
  170. return 1;
  171. }
  172. /*!
  173. \brief Deletes feature at the given offset (level 1)
  174. \param Map pointer Map_info structure
  175. \param offset feature offset
  176. \return 0 on success
  177. \return -1 on error
  178. */
  179. int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
  180. {
  181. G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset);
  182. if (!Map->fInfo.ogr.layer) {
  183. G_warning(_("OGR layer not defined"));
  184. return -1;
  185. }
  186. if (offset >= Map->fInfo.ogr.offset_num)
  187. return -1;
  188. if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer, Map->fInfo.ogr.offset[offset]) != OGRERR_NONE)
  189. return -1;
  190. return 0;
  191. }
  192. /*!
  193. \brief Deletes feature (topology level).
  194. \param Map pointer to Map_info structure
  195. \param line feature id
  196. \return 0 on success
  197. \return -1 on error
  198. */
  199. int V2_delete_line_ogr(struct Map_info *Map, int line)
  200. {
  201. return V2__delete_line(Map, line, V1_delete_line_ogr);
  202. }
  203. #endif /* HAVE_OGR */