From ffaa43069530312280cd007228427834eabe8812 Mon Sep 17 00:00:00 2001 From: Benjamin Ducke Date: Fri, 14 Jan 2011 22:58:48 +0000 Subject: [PATCH] This commit contains some small bugfixes, code clean-ups, performance improvement, and a new feature for v.out.ogr. 1. Fixed a but that would spawn ugly error messages in conjunction with the "-s" flag 2. Reduced the SQL SELECT statements to just one instead of one per feature, increasing output speed by several magnitudes. 3. Added a new "-z" flag, which provides a simple and robust means of producing 3D ESRI Shapefiles --> Please test intensively! git-svn-id: https://svn.osgeo.org/grass/grass/trunk@45044 15284696-431f-4ddb-bdfa-cd5b030d7da7 --- vector/v.out.ogr/args.c | 5 + vector/v.out.ogr/attrb.c | 24 +-- vector/v.out.ogr/local_proto.h | 9 +- vector/v.out.ogr/main.c | 306 ++++++++++++++++++-------------- vector/v.out.ogr/v.out.ogr.html | 8 + 5 files changed, 205 insertions(+), 147 deletions(-) diff --git a/vector/v.out.ogr/args.c b/vector/v.out.ogr/args.c index 69f1445fc6d..e1f78e724fa 100644 --- a/vector/v.out.ogr/args.c +++ b/vector/v.out.ogr/args.c @@ -95,6 +95,11 @@ void parse_args(int argc, char **argv, flags->esristyle->description = _("Use ESRI-style .prj file format " "(applies to Shapefile output only)"); flags->esristyle->guisection = _("Creation"); + + flags->shapez = G_define_flag(); + flags->shapez->key = 'z'; + flags->shapez->description = _("Create 3D output if input is 3D " + "(applies to Shapefile output only)"); flags->poly = G_define_flag(); flags->poly->key = 'p'; diff --git a/vector/v.out.ogr/attrb.c b/vector/v.out.ogr/attrb.c index f4bc68f20e0..10769c9a7c1 100644 --- a/vector/v.out.ogr/attrb.c +++ b/vector/v.out.ogr/attrb.c @@ -4,15 +4,13 @@ int mk_att(int cat, struct field_info *Fi, dbDriver *Driver, int ncol, int doatt, int nocat, OGRFeatureH Ogr_feature, int *noatt, - int *fout) + int *fout, dbCursor cursor) { int j, ogrfieldnum; - char buf[2000]; int colsqltype, colctype, more; dbTable *Table; dbString dbstring; dbColumn *Column; - dbCursor cursor; dbValue *Value; G_debug(2, "mk_att() cat = %d, doatt = %d", cat, doatt); @@ -30,16 +28,6 @@ int mk_att(int cat, struct field_info *Fi, dbDriver *Driver, int ncol, /* Read & set attributes */ if (cat >= 0) { /* Line with category */ if (doatt) { - sprintf(buf, "SELECT * FROM %s WHERE %s = %d", Fi->table, Fi->key, - cat); - G_debug(2, "SQL: %s", buf); - db_set_string(&dbstring, buf); - if (db_open_select_cursor - (Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) { - G_fatal_error(_("Cannot select attributes for cat = %d"), - cat); - } - else { if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) G_fatal_error(_("Unable to fetch data from table")); if (!more) { @@ -76,10 +64,15 @@ int mk_att(int cat, struct field_info *Fi, dbDriver *Driver, int ncol, db_get_column_name(Column), ogrfieldnum); /* Reset */ - OGR_F_UnsetField(Ogr_feature, ogrfieldnum); + if ( ( ( nocat ) && (strcmp(Fi->key, db_get_column_name(Column)) == 0) ) == 0 ) { + /* if this is 'cat', then execute the following only if the '-s' flag was NOT given*/ + OGR_F_UnsetField(Ogr_feature, ogrfieldnum); + } /* prevent writing NULL values */ if (!db_test_value_isnull(Value)) { + if ( ( (nocat) && (strcmp(Fi->key, db_get_column_name(Column)) == 0) ) == 0 ) { + /* if this is 'cat', then execute the following only if the '-s' flag was NOT given*/ switch (colctype) { case DB_C_TYPE_INT: OGR_F_SetFieldInteger(Ogr_feature, @@ -107,9 +100,8 @@ int mk_att(int cat, struct field_info *Fi, dbDriver *Driver, int ncol, } } } + } } - db_close_cursor(&cursor); - } } else { /* Use cat only */ ogrfieldnum = OGR_F_GetFieldIndex(Ogr_feature, "cat"); diff --git a/vector/v.out.ogr/local_proto.h b/vector/v.out.ogr/local_proto.h index f87dab24c2c..462207eaf8f 100644 --- a/vector/v.out.ogr/local_proto.h +++ b/vector/v.out.ogr/local_proto.h @@ -5,13 +5,18 @@ #include "ogr_api.h" #include "cpl_string.h" + +/* some hard limits */ +#define SQL_BUFFER_SIZE 2000 + + struct Options { struct Option *input, *dsn, *layer, *type, *format, *field, *dsco, *lco; }; struct Flags { - struct Flag *cat, *esristyle, *poly, *update, *nocat, *new, *append; + struct Flag *cat, *esristyle, *poly, *update, *nocat, *new, *append, *shapez; }; /* args.c */ @@ -20,7 +25,7 @@ void parse_args(int, char **, /* attributes.c */ int mk_att(int cat, struct field_info *Fi, dbDriver *Driver, - int ncol, int doatt, int nocat, OGRFeatureH Ogr_feature, int *, int *); + int ncol, int doatt, int nocat, OGRFeatureH Ogr_feature, int *, int *, dbCursor cursor); /* list.c */ char *OGR_list_write_drivers(); diff --git a/vector/v.out.ogr/main.c b/vector/v.out.ogr/main.c index 305c495a71a..387023786af 100644 --- a/vector/v.out.ogr/main.c +++ b/vector/v.out.ogr/main.c @@ -20,6 +20,7 @@ #include #include + #include #include #include @@ -37,9 +38,8 @@ int main(int argc, char *argv[]) struct Options options; struct Flags flags; - char buf[2000]; - char key1[200], key2[200]; - struct Key_Value *projinfo, *projunits; + char buf[SQL_BUFFER_SIZE]; + char key1[SQL_BUFFER_SIZE], key2[SQL_BUFFER_SIZE]; struct Key_Value *projinfo, *projunits; struct Cell_head cellhd; char **tokens; @@ -56,6 +56,7 @@ int main(int argc, char *argv[]) dbTable *Table; dbString dbstring; dbColumn *Column; + dbCursor cursor; int fout, fskip; /* features written/ skip */ int nocat, noatt, nocatskip; /* number of features without cats/atts written/skip */ @@ -263,6 +264,133 @@ int main(int argc, char *argv[]) G_warning(_("The map contains islands. With the -c flag, " "islands will appear as filled areas, not holes in the output map.")); + + /* check what users wants to export and what's present in the map */ + if (Vect_get_num_primitives(&In, GV_POINT) > 0 && !(otype & GV_POINTS)) + G_warning(_("%d point(s) found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_primitives(&In, + GV_POINT)); + + if (Vect_get_num_primitives(&In, GV_LINE) > 0 && !(otype & GV_LINES)) + G_warning(_("%d line(s) found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_primitives(&In, + GV_LINE)); + + if (Vect_get_num_primitives(&In, GV_BOUNDARY) > 0 && + !(otype & GV_BOUNDARY) && !(otype & GV_AREA)) + G_warning(_("%d boundary(ies) found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_primitives(&In, + GV_BOUNDARY)); + + if (Vect_get_num_primitives(&In, GV_CENTROID) > 0 && + !(otype & GV_CENTROID) && !(otype & GV_AREA)) + G_warning(_("%d centroid(s) found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_primitives(&In, + GV_CENTROID)); + + if (Vect_get_num_areas(&In) > 0 && !(otype & GV_AREA)) + G_warning(_("%d areas found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_areas(&In)); + + if (Vect_get_num_primitives(&In, GV_FACE) > 0 && !(otype & GV_FACE)) + G_warning(_("%d faces found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_primitives(&In, + GV_FACE)); + + if (Vect_get_num_volumes(&In) > 0 && !(otype & GV_VOLUME)) + G_warning(_("%d volume(s) found, but not requested to be exported. " + "Verify 'type' parameter."), Vect_get_num_volumes(&In)); + + /* warn and eventually abort if there is nothing to be exported */ + num_to_export = 0; + if (Vect_get_num_primitives(&In, GV_POINT) < 1 && (otype & GV_POINTS)) { + G_warning(_("No points found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_POINT) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_POINT); + } + + if (Vect_get_num_primitives(&In, GV_LINE) < 1 && (otype & GV_LINE)) { + G_warning(_("No lines found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_LINE) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_LINE); + } + + if (Vect_get_num_primitives(&In, GV_BOUNDARY) < 1 && + (otype & GV_BOUNDARY)) { + G_warning(_("No boundaries found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_BOUNDARY) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_BOUNDARY); + } + + if (Vect_get_num_areas(&In) < 1 && (otype & GV_AREA)) { + G_warning(_("No areas found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_AREA) + num_to_export = num_to_export + Vect_get_num_areas(&In); + } + + if (Vect_get_num_primitives(&In, GV_CENTROID) < 1 && + (otype & GV_CENTROID)) { + G_warning(_("No centroids found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_CENTROID) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_CENTROID); + } + + if (Vect_get_num_primitives(&In, GV_FACE) < 1 && (otype & GV_FACE)) { + G_warning(_("No faces found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_FACE) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_FACE); + } + + if (Vect_get_num_primitives(&In, GV_KERNEL) < 1 && (otype & GV_KERNEL)) { + G_warning(_("No kernels found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_KERNEL) + num_to_export = + num_to_export + Vect_get_num_primitives(&In, GV_KERNEL); + } + + if (Vect_get_num_volumes(&In) < 1 && (otype & GV_VOLUME)) { + G_warning(_("No volumes found, but requested to be exported. " + "Will skip this feature type.")); + } + else { + if (otype & GV_VOLUME) + num_to_export = num_to_export + Vect_get_num_volumes(&In); + } + + G_debug(1, "Requested to export %d features", num_to_export); + + if (num_to_export < 1) { + G_warning(_("Nothing to export")); + exit(EXIT_SUCCESS); + } + + /* Open OGR DSN */ G_debug(2, "driver count = %d", OGRGetDriverCount()); drn = -1; @@ -327,6 +455,36 @@ int main(int argc, char *argv[]) } } } + + /* Automatically append driver options for 3D output to + layer creation options if 'z' is given.*/ + if ((flags.shapez->answer) && (Vect_is_3d(&In)) && (strcmp(options.format->answer, + "ESRI_Shapefile") == 0)) { + /* find right option */ + char shape_geom[20]; + if ((otype & GV_POINTS) || (otype & GV_KERNEL)) + sprintf(shape_geom, "POINTZ"); + if ((otype & GV_LINES)) + sprintf(shape_geom, "ARCZ"); + if ((otype & GV_AREA) || (otype & GV_FACE)) + sprintf(shape_geom, "POLYGONZ"); + /* check if the right LCO is already present */ + const char *shpt; + shpt = CSLFetchNameValue(papszLCO, "SHPT"); + if ((!shpt)) { + /* Not set at all? Good! */ + papszLCO = CSLSetNameValue(papszLCO, "SHPT", shape_geom); + } else { + if (strcmp(shpt, shape_geom) != 0) { + /* Set but to a different value? Override! */ + G_warning(_("Overriding existing user-defined 'SHPT=' LCO.")); + } + /* Set correct LCO for this geometry type */ + papszLCO = CSLSetNameValue(papszLCO, "SHPT", shape_geom); + } + } + + /* check if the map is 3d */ if (Vect_is_3d(&In)) { /* specific check for ESRI ShapeFile */ @@ -337,7 +495,7 @@ int main(int argc, char *argv[]) if (!shpt || shpt[strlen(shpt) - 1] != 'Z') { G_warning(_("Vector map <%s> is 3D. " "Use format specific layer creation options SHPT (parameter 'lco') " - "to export in 3D rather than 2D (default)"), + "or '-z' flag to export in 3D rather than 2D (default)"), options.input->answer); } } @@ -485,130 +643,19 @@ int main(int argc, char *argv[]) fout = fskip = nocat = noatt = nocatskip = 0; - /* check what users wants to export and what's present in the map */ - if (Vect_get_num_primitives(&In, GV_POINT) > 0 && !(otype & GV_POINTS)) - G_warning(_("%d point(s) found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_primitives(&In, - GV_POINT)); - - if (Vect_get_num_primitives(&In, GV_LINE) > 0 && !(otype & GV_LINES)) - G_warning(_("%d line(s) found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_primitives(&In, - GV_LINE)); - - if (Vect_get_num_primitives(&In, GV_BOUNDARY) > 0 && - !(otype & GV_BOUNDARY) && !(otype & GV_AREA)) - G_warning(_("%d boundary(ies) found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_primitives(&In, - GV_BOUNDARY)); - - if (Vect_get_num_primitives(&In, GV_CENTROID) > 0 && - !(otype & GV_CENTROID) && !(otype & GV_AREA)) - G_warning(_("%d centroid(s) found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_primitives(&In, - GV_CENTROID)); - - if (Vect_get_num_areas(&In) > 0 && !(otype & GV_AREA)) - G_warning(_("%d areas found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_areas(&In)); - - if (Vect_get_num_primitives(&In, GV_FACE) > 0 && !(otype & GV_FACE)) - G_warning(_("%d faces found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_primitives(&In, - GV_FACE)); - - if (Vect_get_num_volumes(&In) > 0 && !(otype & GV_VOLUME)) - G_warning(_("%d volume(s) found, but not requested to be exported. " - "Verify 'type' parameter."), Vect_get_num_volumes(&In)); - - /* warn and eventually abort if there is nothing to be exported */ - num_to_export = 0; - if (Vect_get_num_primitives(&In, GV_POINT) < 1 && (otype & GV_POINTS)) { - G_warning(_("No points found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_POINT) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_POINT); - } - - if (Vect_get_num_primitives(&In, GV_LINE) < 1 && (otype & GV_LINE)) { - G_warning(_("No lines found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_LINE) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_LINE); - } - if (Vect_get_num_primitives(&In, GV_BOUNDARY) < 1 && - (otype & GV_BOUNDARY)) { - G_warning(_("No boundaries found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_BOUNDARY) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_BOUNDARY); - } - - if (Vect_get_num_areas(&In) < 1 && (otype & GV_AREA)) { - G_warning(_("No areas found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_AREA) - num_to_export = num_to_export + Vect_get_num_areas(&In); - } - - if (Vect_get_num_primitives(&In, GV_CENTROID) < 1 && - (otype & GV_CENTROID)) { - G_warning(_("No centroids found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_CENTROID) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_CENTROID); - } - - if (Vect_get_num_primitives(&In, GV_FACE) < 1 && (otype & GV_FACE)) { - G_warning(_("No faces found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_FACE) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_FACE); - } - - if (Vect_get_num_primitives(&In, GV_KERNEL) < 1 && (otype & GV_KERNEL)) { - G_warning(_("No kernels found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_KERNEL) - num_to_export = - num_to_export + Vect_get_num_primitives(&In, GV_KERNEL); - } - - if (Vect_get_num_volumes(&In) < 1 && (otype & GV_VOLUME)) { - G_warning(_("No volumes found, but requested to be exported. " - "Will skip this feature type.")); - } - else { - if (otype & GV_VOLUME) - num_to_export = num_to_export + Vect_get_num_volumes(&In); + /* Fetch all attribute records */ + if (doatt) { + sprintf(buf, "SELECT * FROM %s", Fi->table); + G_debug(2, "SQL: %s", buf); + db_set_string(&dbstring, buf); + if (db_open_select_cursor + (Driver, &dbstring, &cursor, DB_SEQUENTIAL) != DB_OK) { + G_fatal_error(_("Cannot select attributes for cat = %d"), + cat); + } } - G_debug(1, "Requested to export %d features", num_to_export); - - if (num_to_export < 1) { - G_warning(_("Nothing to export")); - exit(EXIT_SUCCESS); - } /* Lines (run always to count features of different type) */ if ((otype & GV_POINTS) || (otype & GV_LINES)) { @@ -683,7 +730,7 @@ int main(int argc, char *argv[]) } mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, - Ogr_feature, &noatt, &fout); + Ogr_feature, &noatt, &fout, cursor); OGR_L_CreateFeature(Ogr_layer, Ogr_feature); } OGR_G_DestroyGeometry(Ogr_geometry); @@ -758,7 +805,7 @@ int main(int argc, char *argv[]) } mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, - Ogr_feature, &noatt, &fout); + Ogr_feature, &noatt, &fout, cursor); OGR_L_CreateFeature(Ogr_layer, Ogr_feature); } OGR_G_DestroyGeometry(Ogr_geometry); @@ -818,7 +865,7 @@ int main(int argc, char *argv[]) } mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, - Ogr_feature, &noatt, &fout); + Ogr_feature, &noatt, &fout, cursor); OGR_L_CreateFeature(Ogr_layer, Ogr_feature); } @@ -873,7 +920,7 @@ int main(int argc, char *argv[]) } mk_att(cat, Fi, Driver, ncol, doatt, flags.nocat->answer, - Ogr_feature, &noatt, &fout); + Ogr_feature, &noatt, &fout, cursor); OGR_L_CreateFeature(Ogr_layer, Ogr_feature); } OGR_G_DestroyGeometry(Ogr_geometry); @@ -898,6 +945,7 @@ int main(int argc, char *argv[]) Vect_close(&In); if (doatt) { + db_close_cursor(&cursor); db_close_database(Driver); db_shutdown_driver(Driver); } diff --git a/vector/v.out.ogr/v.out.ogr.html b/vector/v.out.ogr/v.out.ogr.html index e09caf03246..873ea042515 100644 --- a/vector/v.out.ogr/v.out.ogr.html +++ b/vector/v.out.ogr/v.out.ogr.html @@ -26,6 +26,9 @@

NOTES

By default, islands will appear as holes inside surrounding areas. To export areas with holes into, e.g., a Shapefile, and make the holes appear as filled areas, the flag -c has to be used. +

+The "-z" flag can be used to automatically export a 3D map to a 3D Shapefile, instead +of setting the correct lco= option manually.

EXAMPLES

@@ -56,6 +59,11 @@

Export to Shapefile

 v.out.ogr input=objects_3d type=face dsn=faces_3d.shp lco="SHPT=POLYGONZ"
 
+

+Export 3D faces from GRASS vector map to Shapefile format, automatic 3D setting: +

+v.out.ogr input=objects_3d type=face dsn=faces_3d.shp -z"
+

Export to GML