/*! \file vector/Vlib/write_ogr.c \brief Vector library - write vector feature (OGR format) Higher level functions for reading/writing/manipulating vectors. Inspired by v.out.ogr's code. (C) 2009-2010 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. \author Martin Landa */ #include #include #include #include #ifdef HAVE_OGR #include static int write_attributes(int, const struct field_info *, OGRLayerH, OGRFeatureH); /*! \brief Writes feature on level 1 (OGR format) \param Map pointer to Map_info structure \param type feature type \param points pointer to line_pnts structure (feature geometry) \param cats pointer to line_cats structure (feature categories) \return feature offset into file \return -1 on error */ off_t V1_write_line_ogr(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats) { int i, cat, ret; struct field_info *Fi; OGRGeometryH Ogr_geometry; OGRFeatureH Ogr_feature; OGRFeatureDefnH Ogr_featuredefn; if (!Map->fInfo.ogr.layer) { G_warning(_("OGR layer not defined")); return -1; } /* determine feature's geometry */ if (type & (GV_POINTS | GV_KERNEL)) { Ogr_geometry = OGR_G_CreateGeometry(wkbPoint); } else if (type & GV_LINES) { Ogr_geometry = OGR_G_CreateGeometry(wkbLineString); } else if (type & GV_FACE) { Ogr_geometry = OGR_G_CreateGeometry(wkbPolygon25D); } else { G_warning("V1_write_line_ogr(): %s (%d)", _("Unsupported feature type"), type); return -1; } G_debug(3, "V1_write_line_ogr(): type = %d", type); for (i = 0; i < points->n_points; i++) { OGR_G_AddPoint(Ogr_geometry, points->x[i], points->y[i], points->z[i]); } G_debug(4, " n_points = %d", points->n_points); Ogr_featuredefn = OGR_L_GetLayerDefn(Map->fInfo.ogr.layer); /* create feature & set geometry */ Ogr_feature = OGR_F_Create(Ogr_featuredefn); OGR_F_SetGeometry(Ogr_feature, Ogr_geometry); /* write attributes */ if (cats->n_cats > 0) { cat = cats->cat[0]; if (cats->n_cats > 1) { G_warning(_("Feature has more categories, using " "category %d (from layer %d)"), cat, cats->field[0]); } Fi = Vect_get_field(Map, cats->field[0]); if (!Fi) { G_fatal_error(_("Database connection not defined for layer %d"), cats->field[0]); } write_attributes(cat, Fi, Map->fInfo.ogr.layer, Ogr_feature); } else { /* no attributes */ G_warning(_("Feature has no categories")); } /* write feature into layer */ ret = OGR_L_CreateFeature(Map->fInfo.ogr.layer, Ogr_feature); /* destroy */ OGR_G_DestroyGeometry(Ogr_geometry); OGR_F_Destroy(Ogr_feature); if (ret != OGRERR_NONE) return -1; return Map->fInfo.ogr.offset_num++; } /*! \brief Writes feature to 'coor' file (topology level) \param Map pointer to Map_info structure \param type feature type \param points feature geometry \param cats feature categories \return new feature id \return -1 on error */ off_t V2_write_line_ogr(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats) { return V2__write_line(Map, type, points, cats, V1_write_line_ogr); } /*! \brief Deletes feature at the given offset (level 1) \param Map pointer Map_info structure \param offset feature offset \return 0 on success \return -1 on error */ int V1_delete_line_ogr(struct Map_info *Map, off_t offset) { G_debug(3, "V1_delete_line_ogr(), offset = %lu", (unsigned long) offset); if (!Map->fInfo.ogr.layer) { G_warning(_("OGR layer not defined")); return -1; } if (offset >= Map->fInfo.ogr.offset_num) return -1; if (OGR_L_DeleteFeature(Map->fInfo.ogr.layer, Map->fInfo.ogr.offset[offset]) != OGRERR_NONE) return -1; return 0; } /*! \brief Deletes feature (topology level). \param Map pointer to Map_info structure \param line feature id \return 0 on success \return -1 on error */ int V2_delete_line_ogr(struct Map_info *Map, int line) { return V2__delete_line(Map, line, V1_delete_line_ogr); } int write_attributes(int cat, const struct field_info *Fi, OGRLayerH Ogr_layer, OGRFeatureH Ogr_feature) { int j, ogrfieldnum; char buf[2000]; int ncol, colsqltype, colctype, more; char *fidcol; dbDriver *Driver; dbTable *Table; dbString dbstring; dbColumn *Column; dbCursor cursor; dbValue *Value; G_debug(3, "write_attributes(): cat = %d", cat); if (cat < 0) { G_warning ("Feature without category of layer %d", Fi->number); return 0; } db_init_string(&dbstring); /* read & set attributes */ sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key, cat); G_debug(4, "SQL: %s", buf); db_set_string(&dbstring, buf); /* open driver & select data */ Driver = db_start_driver_open_database(Fi->driver, Fi->database); if (!Driver) G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); if (db_open_select_cursor(Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) { G_fatal_error(_("Unable to select attributes for category %d"), cat); } if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) { G_fatal_error(_("Unable to fetch data from table <%s>"), Fi->table); } if (!more) { G_warning (_("No database record for category %d - export of 'cat' disabled"), cat); return -1; } fidcol = OGR_L_GetFIDColumn(Ogr_layer); Table = db_get_cursor_table(&cursor); ncol = db_get_table_number_of_columns(Table); for (j = 0; j < ncol; j++) { Column = db_get_table_column(Table, j); if (fidcol && strcmp(db_get_column_name(Column), fidcol) == 0) { /* skip fid column */ continue; } Value = db_get_column_value(Column); db_convert_column_value_to_string(Column, &dbstring); /* for debug only */ G_debug(2, "col %d : val = %s", j, db_get_string(&dbstring)); colsqltype = db_get_column_sqltype(Column); colctype = db_sqltype_to_Ctype(colsqltype); G_debug(2, " colctype = %d", colctype); ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, db_get_column_name(Column)); if (ogrfieldnum < 0) { G_warning(_("Uknown column <%s>"), db_get_column_name(Column)); continue; } /* Reset */ OGR_F_UnsetField(Ogr_feature, ogrfieldnum); /* prevent writing NULL values */ if (!db_test_value_isnull(Value)) { switch (colctype) { case DB_C_TYPE_INT: OGR_F_SetFieldInteger(Ogr_feature, ogrfieldnum, db_get_value_int(Value)); break; case DB_C_TYPE_DOUBLE: OGR_F_SetFieldDouble(Ogr_feature, ogrfieldnum, db_get_value_double(Value)); break; case DB_C_TYPE_STRING: OGR_F_SetFieldString(Ogr_feature, ogrfieldnum, db_get_value_string(Value)); break; case DB_C_TYPE_DATETIME: db_convert_column_value_to_string(Column, &dbstring); OGR_F_SetFieldString(Ogr_feature, ogrfieldnum, db_get_string(&dbstring)); break; } } } db_close_cursor (&cursor); db_close_database(Driver); db_shutdown_driver(Driver); db_free_string(&dbstring); return 1; } #endif /* HAVE_OGR */