source: grass/trunk/vector/v.out.ogr/main.c

Last change on this file was 74408, checked in by neteler, 5 years ago

manual: keyword 'output' added

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 28.7 KB
Line 
1/*
2 ***************************************************************
3 *
4 * MODULE: v.out.ogr
5 *
6 * AUTHOR(S): Radim Blazek
7 * Some extensions: Markus Neteler, Benjamin Ducke
8 * Multi-features support by Martin Landa <landa.martin gmail.com>
9 *
10 * PURPOSE: Converts GRASS vector to one of supported OGR vector formats.
11 *
12 * COPYRIGHT: (C) 2001-2017 by the GRASS Development Team
13 *
14 * This program is free software under the GNU General
15 * Public License (>=v2). Read the file COPYING that
16 * comes with GRASS for details.
17 *
18 **************************************************************/
19
20#include <stdlib.h>
21#include <string.h>
22
23
24#include <grass/gis.h>
25#include <grass/gprojects.h>
26#include <grass/glocale.h>
27
28#include "local_proto.h"
29
30#include <ogr_srs_api.h>
31
32int main(int argc, char *argv[])
33{
34 int i, otype, ftype, donocat;
35 int num_to_export;
36 int field;
37 int overwrite, found;
38
39 struct GModule *module;
40 struct Options options;
41 struct Flags flags;
42
43 char buf[SQL_BUFFER_SIZE];
44 char key1[SQL_BUFFER_SIZE], key2[SQL_BUFFER_SIZE];
45 struct Cell_head cellhd;
46 char **tokens;
47
48 /* Vector */
49 struct Map_info In;
50
51 /* Attributes */
52 int doatt = 0, ncol = 0, colsqltype, colwidth, keycol = -1;
53 int *colctype = NULL;
54 const char **colname = NULL;
55 struct field_info *Fi = NULL;
56 dbDriver *Driver = NULL;
57 dbTable *Table;
58 dbString dbstring;
59 dbColumn *Column;
60
61 int n_feat; /* number of written features */
62 int n_nocat, n_noatt; /* number of features without cats/atts written/skip */
63
64 /* OGR */
65 int drn;
66 OGRFieldType ogr_ftype = OFTInteger;
67 ds_t hDS;
68 dr_t hDriver;
69 OGRLayerH Ogr_layer;
70 OGRFieldDefnH Ogr_field;
71 OGRFeatureDefnH Ogr_featuredefn;
72 OGRwkbGeometryType wkbtype = wkbUnknown;
73 OGRSpatialReferenceH Ogr_projection;
74 char **papszDSCO = NULL, **papszLCO = NULL;
75 int num_types;
76 char *dsn;
77 int outer_ring_ccw;
78
79 G_gisinit(argv[0]);
80
81 /* Module options */
82 module = G_define_module();
83 G_add_keyword(_("vector"));
84 G_add_keyword(_("export"));
85 G_add_keyword(_("output"));
86 G_add_keyword("OGR");
87 G_add_keyword(_("output"));
88
89 module->label =
90 _("Exports a vector map layer to any of the supported OGR vector formats.");
91 module->description = _("By default a vector map layer is exported to OGC GeoPackage format.");
92 module->overwrite = TRUE;
93
94 /* parse & read options */
95 parse_args(argc, argv, &options, &flags);
96
97 if (flags.list->answer) {
98 list_formats();
99 exit(EXIT_SUCCESS);
100 }
101
102 /* check for weird options */
103 if (G_strncasecmp(options.dsn->answer, "PG:", 3) == 0 &&
104 strcmp(options.format->answer, "PostgreSQL") != 0)
105 G_warning(_("Data source starts with \"PG:\" prefix, expecting \"PostgreSQL\" "
106 "format (\"%s\" given)"), options.format->answer);
107
108 /* parse dataset creation options */
109 i = 0;
110 while (options.dsco->answers[i]) {
111 tokens = G_tokenize(options.dsco->answers[i], "=");
112 if (G_number_of_tokens(tokens))
113 papszDSCO = CSLSetNameValue(papszDSCO, tokens[0], tokens[1]);
114 G_free_tokens(tokens);
115 i++;
116 }
117
118 /* parse layer creation options */
119 i = 0;
120 while (options.lco->answers[i]) {
121 tokens = G_tokenize(options.lco->answers[i], "=");
122 if (G_number_of_tokens(tokens))
123 papszLCO = CSLSetNameValue(papszLCO, tokens[0], tokens[1]);
124 G_free_tokens(tokens);
125 i++;
126 }
127
128 /*
129 If no output type specified: determine one automatically.
130 Centroids, Boundaries and Kernels always have to be exported
131 explicitly, using the "type=" option.
132 */
133 field = 0;
134 if (!flags.new->answer) {
135 /* open input vector (topology required) */
136 Vect_set_open_level(2);
137 if (Vect_open_old2(&In, options.input->answer, "",
138 options.field->answer) < 0)
139 G_fatal_error(_("Unable to open vector map <%s>"),
140 options.input->answer);
141
142 if (strcmp(options.type->answer, "auto") == 0) {
143 G_debug(2, "Automatic type determination.");
144
145 options.type->answers = G_malloc(sizeof(char *) * 10);
146 G_zero(options.type->answers, sizeof(char *) * 10);
147 num_types = 0;
148
149 if (Vect_get_num_primitives(&In, GV_POINT) > 0) {
150 options.type->answers[num_types++] = G_store("point");
151 G_debug(3, "Adding points to export list.");
152 }
153
154 if (Vect_get_num_primitives(&In, GV_LINE) > 0) {
155 options.type->answers[num_types++] = G_store("line");
156 G_debug(3, "Adding lines to export list.");
157 }
158
159 if (Vect_get_num_areas(&In) > 0) {
160 options.type->answers[num_types++] = G_store("area");
161 G_debug(3, "Adding areas to export list.");
162 }
163
164 /* Faces and volumes:
165 For now, volumes will just be exported as sets of faces.
166 */
167 if (Vect_get_num_primitives(&In, GV_FACE) > 0) {
168 options.type->answers[num_types++] = G_store("face");
169 G_debug(3, "Adding faces to export list.");
170 }
171
172 /* this check HAS TO FOLLOW RIGHT AFTER check for GV_FACE! */
173 if (Vect_get_num_volumes(&In) > 0) {
174 G_warning(_("Volumes will be exported as sets of faces"));
175 if (num_types == 0) {
176 /* no other types yet? */
177 options.type->answers[num_types++] = G_store("volume");
178 G_debug(3, "Adding volumes to export list.");
179 }
180 else {
181 if (strcmp(options.type->answers[num_types - 1], "face")
182 != 0) {
183 /* only put faces on export list if that's not the case already */
184 options.type->answers[num_types++] =
185 G_store("volume");
186 G_debug(3, "Adding volumes to export list.");
187 }
188 }
189 }
190
191 if (num_types == 0) {
192 G_warning(_("Unable to determine input map's vector feature type(s)."));
193 }
194 }
195 field = Vect_get_field_number(&In, options.field->answer);
196 }
197
198 /* check output feature type */
199 otype = Vect_option_to_types(options.type);
200 ftype = Vect_option_to_types(options.otype);
201
202 if (!options.layer->answer) {
203 char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
204
205 if (G_name_is_fully_qualified(options.input->answer, xname, xmapset))
206 options.layer->answer = G_store(xname);
207 else
208 options.layer->answer = G_store(options.input->answer);
209 }
210
211 if (ftype == GV_BOUNDARY) {
212 if (!flags.multi->answer)
213 wkbtype = wkbPolygon;
214 else
215 wkbtype = wkbMultiPolygon;
216 }
217 else if (otype & GV_POINTS) {
218 if (!flags.multi->answer)
219 wkbtype = wkbPoint;
220 else
221 wkbtype = wkbMultiPoint;
222 }
223 else if (otype & GV_LINES || ftype == GV_LINE) {
224 if (!flags.multi->answer)
225 wkbtype = wkbLineString;
226 else
227 wkbtype = wkbMultiLineString;
228 }
229 else if (otype & GV_AREA) {
230 if (!flags.multi->answer)
231 wkbtype = wkbPolygon;
232 else
233 wkbtype = wkbMultiPolygon;
234 }
235 else if (otype & (GV_FACE | GV_VOLUME)) {
236 if (!flags.multi->answer)
237 wkbtype = wkbPolygon25D;
238 else
239 wkbtype = wkbMultiPolygon25D;
240 }
241
242 if (((GV_POINTS & otype) && (GV_LINES & otype)) ||
243 ((GV_POINTS & otype) && (GV_AREA & otype)) ||
244 ((GV_POINTS & otype) && (GV_FACE & otype)) ||
245 ((GV_POINTS & otype) && (GV_KERNEL & otype)) ||
246 ((GV_POINTS & otype) && (GV_VOLUME & otype)) ||
247 ((GV_LINES & otype) && (GV_AREA & otype)) ||
248 ((GV_LINES & otype) && (GV_FACE & otype)) ||
249 ((GV_LINES & otype) && (GV_KERNEL & otype)) ||
250 ((GV_LINES & otype) && (GV_VOLUME & otype)) ||
251 ((GV_KERNEL & otype) && (GV_POINTS & otype)) ||
252 ((GV_KERNEL & otype) && (GV_LINES & otype)) ||
253 ((GV_KERNEL & otype) && (GV_AREA & otype)) ||
254 ((GV_KERNEL & otype) && (GV_FACE & otype)) ||
255 ((GV_KERNEL & otype) && (GV_VOLUME & otype))
256 ) {
257 G_warning(_("The combination of types is not supported"
258 " by all formats."));
259 wkbtype = wkbUnknown;
260 }
261
262 /* fetch PROJ info */
263 G_get_default_window(&cellhd);
264 Ogr_projection = NULL;
265 if (cellhd.proj != PROJECTION_XY) {
266 struct Key_Value *projinfo, *projunits, *projepsg;
267
268 projinfo = G_get_projinfo();
269 projunits = G_get_projunits();
270 projepsg = G_get_projepsg();
271 Ogr_projection = GPJ_grass_to_osr2(projinfo, projunits, projepsg);
272
273 if (Ogr_projection == NULL)
274 G_fatal_error(_("Unable to create OGR spatial reference"));
275
276 if (flags.esristyle->answer &&
277 (strcmp(options.format->answer, "ESRI_Shapefile") == 0))
278 OSRMorphToESRI(Ogr_projection);
279 }
280
281 dsn = NULL;
282 if (options.dsn->answer)
283 dsn = G_store(options.dsn->answer);
284
285 /* create new OGR layer in datasource */
286 if (flags.new->answer) {
287 const char *name;
288
289 name =
290 options.layer->answer ? options.layer->answer : options.input->
291 answer;
292
293 create_ogr_layer(dsn, options.format->answer, name,
294 wkbtype, papszDSCO, papszLCO);
295
296 G_message(_("OGR layer <%s> created in datasource <%s> (format '%s')"),
297 name, options.dsn->answer, options.format->answer);
298 exit(EXIT_SUCCESS);
299 }
300
301 if (flags.cat->answer)
302 donocat = 1;
303 else
304 donocat = 0;
305
306 if ((GV_AREA & otype) && Vect_get_num_islands(&In) > 0 &&
307 flags.cat->answer)
308 G_warning(_("The map contains islands. With the -c flag, "
309 "islands will appear as filled areas, not holes in the output map."));
310
311
312 /* check what users wants to export and what's present in the map */
313 if (Vect_get_num_primitives(&In, GV_POINT) > 0 && !(otype & GV_POINTS))
314 G_warning(n_("%d point found, but not requested to be exported. "
315 "Verify 'type' parameter.",
316 "%d points found, but not requested to be exported. "
317 "Verify 'type' parameter.",
318 Vect_get_num_primitives(&In, GV_POINT)),
319 Vect_get_num_primitives(&In, GV_POINT));
320
321 if (Vect_get_num_primitives(&In, GV_LINE) > 0 && !(otype & GV_LINES))
322 G_warning(n_("%d line found, but not requested to be exported. "
323 "Verify 'type' parameter.",
324 "%d line(s) found, but not requested to be exported. "
325 "Verify 'type' parameter.",
326 Vect_get_num_primitives(&In, GV_LINE)),
327 Vect_get_num_primitives(&In, GV_LINE));
328
329 if (Vect_get_num_primitives(&In, GV_BOUNDARY) > 0 &&
330 !(otype & GV_BOUNDARY) && !(otype & GV_AREA))
331 G_warning(n_("%d boundary found, but not requested to be exported. "
332 "Verify 'type' parameter.",
333 "%d boundaries found, but not requested to be exported. "
334 "Verify 'type' parameter.",
335 Vect_get_num_primitives(&In, GV_BOUNDARY)),
336 Vect_get_num_primitives(&In, GV_BOUNDARY));
337
338 if (Vect_get_num_primitives(&In, GV_CENTROID) > 0 &&
339 !(otype & GV_CENTROID) && !(otype & GV_AREA))
340 G_warning(n_("%d centroid found, but not requested to be exported. "
341 "Verify 'type' parameter.",
342 "%d centroids found, but not requested to be exported. "
343 "Verify 'type' parameter.",
344 Vect_get_num_primitives(&In, GV_CENTROID)),
345 Vect_get_num_primitives(&In, GV_CENTROID));
346
347 if (Vect_get_num_areas(&In) > 0 && !(otype & GV_AREA))
348 G_warning(n_("%d area found, but not requested to be exported. "
349 "Verify 'type' parameter.",
350 "%d areas found, but not requested to be exported. "
351 "Verify 'type' parameter.",
352 Vect_get_num_areas(&In)),
353 Vect_get_num_areas(&In));
354
355 if (Vect_get_num_primitives(&In, GV_FACE) > 0 && !(otype & GV_FACE))
356 G_warning(n_("%d face found, but not requested to be exported. "
357 "Verify 'type' parameter.",
358 "%d faces found, but not requested to be exported. "
359 "Verify 'type' parameter.",
360 Vect_get_num_primitives(&In, GV_FACE)),
361 Vect_get_num_primitives(&In, GV_FACE));
362
363 if (Vect_get_num_volumes(&In) > 0 && !(otype & GV_VOLUME))
364 G_warning(n_("%d volume found, but not requested to be exported. "
365 "Verify 'type' parameter.",
366 "%d volumes found, but not requested to be exported. "
367 "Verify 'type' parameter.",
368 Vect_get_num_volumes(&In)),
369 Vect_get_num_volumes(&In));
370
371 /* warn and eventually abort if there is nothing to be exported */
372 num_to_export = 0;
373 if (Vect_get_num_primitives(&In, GV_POINT) < 1 && (otype & GV_POINTS)) {
374 G_warning(_("No points found, but requested to be exported. "
375 "Will skip this feature type."));
376 }
377 else {
378 if (otype & GV_POINT)
379 num_to_export += Vect_get_num_primitives(&In, GV_POINT);
380 }
381
382 if (Vect_get_num_primitives(&In, GV_LINE) < 1 && (otype & GV_LINE)) {
383 G_warning(_("No lines found, but requested to be exported. "
384 "Will skip this feature type."));
385 }
386 else {
387 if (otype & GV_LINE)
388 num_to_export += Vect_get_num_primitives(&In, GV_LINE);
389 }
390
391 if (Vect_get_num_primitives(&In, GV_BOUNDARY) < 1 &&
392 (otype & GV_BOUNDARY)) {
393 G_warning(_("No boundaries found, but requested to be exported. "
394 "Will skip this feature type."));
395 }
396 else {
397 if (otype & GV_BOUNDARY)
398 num_to_export += Vect_get_num_primitives(&In, GV_BOUNDARY);
399 }
400
401 if (Vect_get_num_areas(&In) < 1 && (otype & GV_AREA)) {
402 G_warning(_("No areas found, but requested to be exported. "
403 "Will skip this feature type."));
404 }
405 else {
406 if (otype & GV_AREA)
407 num_to_export += Vect_get_num_areas(&In);
408 }
409
410 if (Vect_get_num_primitives(&In, GV_CENTROID) < 1 &&
411 (otype & GV_CENTROID)) {
412 G_warning(_("No centroids found, but requested to be exported. "
413 "Will skip this feature type."));
414 }
415 else {
416 if (otype & GV_CENTROID)
417 num_to_export += Vect_get_num_primitives(&In, GV_CENTROID);
418 }
419
420 if (Vect_get_num_primitives(&In, GV_FACE) < 1 && (otype & GV_FACE)) {
421 G_warning(_("No faces found, but requested to be exported. "
422 "Will skip this feature type."));
423 }
424 else {
425 if (otype & GV_FACE)
426 num_to_export += Vect_get_num_primitives(&In, GV_FACE);
427 }
428
429 if (Vect_get_num_primitives(&In, GV_KERNEL) < 1 && (otype & GV_KERNEL)) {
430 G_warning(_("No kernels found, but requested to be exported. "
431 "Will skip this feature type."));
432 }
433 else {
434 if (otype & GV_KERNEL)
435 num_to_export += Vect_get_num_primitives(&In, GV_KERNEL);
436 }
437
438 if (Vect_get_num_volumes(&In) < 1 && (otype & GV_VOLUME)) {
439 G_warning(_("No volumes found, but requested to be exported. "
440 "Will skip this feature type."));
441 }
442 else {
443 if (otype & GV_VOLUME)
444 num_to_export += Vect_get_num_volumes(&In);
445 }
446
447 G_debug(1, "Requested to export %d features", num_to_export);
448
449 /* Open OGR DSN */
450#if GDAL_VERSION_NUM >= 2020000
451 G_debug(2, "driver count = %d", GDALGetDriverCount());
452 drn = -1;
453 for (i = 0; i < GDALGetDriverCount(); i++) {
454 hDriver = GDALGetDriver(i);
455 G_debug(2, "driver %d : %s", i, GDALGetDriverShortName(hDriver));
456 /* chg white space to underscore in OGR driver names */
457 sprintf(buf, "%s", GDALGetDriverShortName(hDriver));
458 G_strchg(buf, ' ', '_');
459 if (strcmp(buf, options.format->answer) == 0) {
460 drn = i;
461 G_debug(2, " -> driver = %d", drn);
462 }
463 }
464#else
465 G_debug(2, "driver count = %d", OGRGetDriverCount());
466 drn = -1;
467 for (i = 0; i < OGRGetDriverCount(); i++) {
468 hDriver = OGRGetDriver(i);
469 G_debug(2, "driver %d : %s", i, OGR_Dr_GetName(hDriver));
470 /* chg white space to underscore in OGR driver names */
471 sprintf(buf, "%s", OGR_Dr_GetName(hDriver));
472 G_strchg(buf, ' ', '_');
473 if (strcmp(buf, options.format->answer) == 0) {
474 drn = i;
475 G_debug(2, " -> driver = %d", drn);
476 }
477 }
478#endif
479 if (drn == -1)
480 G_fatal_error(_("OGR driver <%s> not found"), options.format->answer);
481 hDriver = get_driver(drn);
482
483 if (flags.append->answer) {
484 G_debug(1, "Append to OGR layer");
485#if GDAL_VERSION_NUM >= 2020000
486 hDS = GDALOpenEx(dsn, GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL);
487
488 if (hDS == NULL) {
489 G_debug(1, "Create OGR data source");
490 hDS = GDALCreate(hDriver, dsn, 0, 0, 0, GDT_Unknown, papszDSCO);
491 }
492#else
493 hDS = OGR_Dr_Open(hDriver, dsn, TRUE);
494
495 if (hDS == NULL) {
496 G_debug(1, "Create OGR data source");
497 hDS = OGR_Dr_CreateDataSource(hDriver, dsn, papszDSCO);
498 }
499#endif
500 }
501 else {
502#if GDAL_VERSION_NUM >= 2020000
503 if (flags.update->answer) {
504 G_debug(1, "Update OGR data source");
505 hDS = GDALOpenEx(dsn, GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL);
506 }
507 else {
508 G_debug(1, "Create OGR data source");
509 hDS = GDALCreate(hDriver, dsn, 0, 0, 0, GDT_Unknown, papszDSCO);
510 }
511#else
512 if (flags.update->answer) {
513 G_debug(1, "Update OGR data source");
514 hDS = OGR_Dr_Open(hDriver, dsn, TRUE);
515 }
516 else {
517 G_debug(1, "Create OGR data source");
518 hDS = OGR_Dr_CreateDataSource(hDriver, dsn, papszDSCO);
519 }
520#endif
521 }
522
523 CSLDestroy(papszDSCO);
524 if (hDS == NULL)
525 G_fatal_error(_("Unable to open OGR data source '%s'"),
526 options.dsn->answer);
527
528 /* check if OGR layer exists */
529 overwrite = G_check_overwrite(argc, argv);
530 found = FALSE;
531#if GDAL_VERSION_NUM >= 2020000
532 for (i = 0; i < GDALDatasetGetLayerCount(hDS); i++) {
533 Ogr_layer = GDALDatasetGetLayer(hDS, i);
534#else
535 for (i = 0; i < OGR_DS_GetLayerCount(hDS); i++) {
536 Ogr_layer = OGR_DS_GetLayer(hDS, i);
537
538#endif
539 Ogr_field = OGR_L_GetLayerDefn(Ogr_layer);
540 if (G_strcasecmp(OGR_FD_GetName(Ogr_field), options.layer->answer))
541 continue;
542
543 found = TRUE;
544 if (!overwrite && !flags.append->answer) {
545 G_fatal_error(_("Layer <%s> already exists in OGR data source '%s'"),
546 options.layer->answer, options.dsn->answer);
547 }
548 else if (overwrite) {
549 G_warning(_("OGR layer <%s> already exists and will be overwritten"),
550 options.layer->answer);
551#if GDAL_VERSION_NUM >= 2020000
552 GDALDatasetDeleteLayer(hDS, i);
553#else
554 OGR_DS_DeleteLayer(hDS, i);
555#endif
556 break;
557 }
558 }
559
560 if (flags.append->answer && !found) {
561 G_warning(_("OGR layer <%s> doesn't exists, "
562 "creating new OGR layer instead"),
563 options.layer->answer);
564 flags.append->answer = FALSE;
565 }
566
567 /* Automatically append driver options for 3D output to layer
568 creation options if '2' is not given.*/
569 if (!flags.force2d->answer &&
570 Vect_is_3d(&In) &&
571 strcmp(options.format->answer, "ESRI_Shapefile") == 0) {
572 /* find right option */
573 char shape_geom[20];
574 if ((otype & GV_POINTS) || (otype & GV_KERNEL))
575 sprintf(shape_geom, "POINTZ");
576 if ((otype & GV_LINES))
577 sprintf(shape_geom, "ARCZ");
578 if ((otype & GV_AREA) || (otype & GV_FACE))
579 sprintf(shape_geom, "POLYGONZ");
580 /* check if the right LCO is already present */
581 const char *shpt;
582 shpt = CSLFetchNameValue(papszLCO, "SHPT");
583 if ((!shpt)) {
584 /* Not set at all? Good! */
585 papszLCO = CSLSetNameValue(papszLCO, "SHPT", shape_geom);
586 } else {
587 if (strcmp(shpt, shape_geom) != 0) {
588 /* Set but to a different value? Override! */
589 G_warning(_("Overriding existing user-defined 'SHPT=' LCO."));
590 }
591 /* Set correct LCO for this geometry type */
592 papszLCO = CSLSetNameValue(papszLCO, "SHPT", shape_geom);
593 }
594 }
595
596 /* check if the map is 3d */
597 if (Vect_is_3d(&In)) {
598 /* specific check for ESRI ShapeFile */
599 if (strcmp(options.format->answer, "ESRI_Shapefile") == 0) {
600 const char *shpt;
601
602 shpt = CSLFetchNameValue(papszLCO, "SHPT");
603 if (!shpt || shpt[strlen(shpt) - 1] != 'Z') {
604 G_warning(_("Vector map <%s> is 3D. "
605 "Use format specific layer creation options SHPT (parameter 'lco') "
606 "or '-z' flag to export in 3D rather than 2D (default)"),
607 options.input->answer);
608 }
609 }
610 /* specific check for PostgreSQL */
611 else if (strcmp(options.format->answer, "PostgreSQL") == 0) {
612 const char *dim;
613
614 dim = CSLFetchNameValue(papszLCO, "DIM");
615 if (!dim || strcmp(dim, "3") != 0) {
616 G_warning(_("Vector map <%s> is 3D. "
617 "Use format specific layer creation options DIM (parameter 'lco') "
618 "to export in 3D rather than 2D (default)."),
619 options.input->answer);
620 }
621 }
622 else {
623 G_warning(_("Vector map <%s> is 3D. "
624 "Use format specific layer creation options (parameter 'lco') "
625 "to export <in 3D rather than 2D (default)."),
626 options.input->answer);
627 }
628 }
629
630 G_debug(1, "Create OGR layer");
631#if GDAL_VERSION_NUM >= 2020000
632 if (flags.append->answer)
633 Ogr_layer = GDALDatasetGetLayerByName(hDS, options.layer->answer);
634 else
635 Ogr_layer = GDALDatasetCreateLayer(hDS, options.layer->answer,
636 Ogr_projection, wkbtype,
637 papszLCO);
638#else
639 if (flags.append->answer)
640 Ogr_layer = OGR_DS_GetLayerByName(hDS, options.layer->answer);
641 else
642 Ogr_layer = OGR_DS_CreateLayer(hDS, options.layer->answer,
643 Ogr_projection, wkbtype,
644 papszLCO);
645#endif
646
647 CSLDestroy(papszLCO);
648 if (Ogr_layer == NULL) {
649 if (flags.append->answer)
650 G_fatal_error(_("OGR layer <%s> not found"), options.layer->answer);
651 else
652 G_fatal_error(_("Unable to create OGR layer"));
653 }
654
655 db_init_string(&dbstring);
656
657 /* Vector attributes -> OGR fields */
658 if (field > 0) {
659 G_debug(1, "Create attribute table");
660 doatt = 1; /* do attributes */
661 Fi = Vect_get_field(&In, field);
662 if (Fi == NULL) {
663 char create_field = TRUE;
664 G_warning(_("No attribute table found -> using only category numbers as attributes"));
665 /* if we have no more than a 'cat' column, then that has to
666 be exported in any case */
667 if (flags.nocat->answer) {
668 G_warning(_("Exporting 'cat' anyway, as it is the only attribute table field"));
669 flags.nocat->answer = FALSE;
670 }
671
672 if (flags.append->answer) {
673 Ogr_field = OGR_L_GetLayerDefn(Ogr_layer);
674 if (OGR_FD_GetFieldIndex(Ogr_field, GV_KEY_COLUMN) > -1)
675 create_field = FALSE;
676 else
677 G_warning(_("New attribute column <%s> added to the table"),
678 GV_KEY_COLUMN);
679 }
680
681 if (create_field) {
682 Ogr_field = OGR_Fld_Create(GV_KEY_COLUMN, OFTInteger);
683 if (OGR_L_CreateField(Ogr_layer, Ogr_field, 0) != OGRERR_NONE)
684 G_fatal_error(_("Unable to create column <%s>"),
685 GV_KEY_COLUMN);
686 OGR_Fld_Destroy(Ogr_field);
687 }
688
689 doatt = 0;
690 }
691 else {
692 Driver = db_start_driver_open_database(Fi->driver, Fi->database);
693 if (!Driver)
694 G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
695 Fi->database, Fi->driver);
696
697 db_set_string(&dbstring, Fi->table);
698 if (db_describe_table(Driver, &dbstring, &Table) != DB_OK)
699 G_fatal_error(_("Unable to describe table <%s>"), Fi->table);
700
701 ncol = db_get_table_number_of_columns(Table);
702 G_debug(2, "ncol = %d", ncol);
703 colctype = G_malloc(ncol * sizeof(int));
704 colname = G_malloc(ncol * sizeof(char *));
705 keycol = -1;
706 for (i = 0; i < ncol; i++) {
707 Column = db_get_table_column(Table, i);
708 colname[i] = G_store(db_get_column_name(Column));
709 colsqltype = db_get_column_sqltype(Column);
710 colctype[i] = db_sqltype_to_Ctype(colsqltype);
711 colwidth = db_get_column_length(Column);
712 G_debug(3, "col %d: %s sqltype=%d ctype=%d width=%d",
713 i, colname[i], colsqltype, colctype[i], colwidth);
714
715 switch (colctype[i]) {
716 case DB_C_TYPE_INT:
717 ogr_ftype = OFTInteger;
718 break;
719 case DB_C_TYPE_DOUBLE:
720 ogr_ftype = OFTReal;
721 break;
722 case DB_C_TYPE_STRING:
723 ogr_ftype = OFTString;
724 break;
725 case DB_C_TYPE_DATETIME:
726 ogr_ftype = OFTString;
727 break;
728 }
729 G_debug(2, "ogr_ftype = %d", ogr_ftype);
730
731 strcpy(key1, Fi->key);
732 G_tolcase(key1);
733 strcpy(key2, colname[i]);
734 G_tolcase(key2);
735 if (strcmp(key1, key2) == 0)
736 keycol = i;
737 G_debug(2, "%s x %s -> %s x %s -> keycol = %d", Fi->key,
738 colname[i], key1, key2, keycol);
739
740 if (flags.nocat->answer &&
741 strcmp(Fi->key, colname[i]) == 0)
742 /* skip export of 'cat' field */
743 continue;
744
745 if (flags.append->answer) {
746 Ogr_field = OGR_L_GetLayerDefn(Ogr_layer);
747 if (OGR_FD_GetFieldIndex(Ogr_field, colname[i]) > -1)
748 /* skip existing fields */
749 continue;
750 else
751 G_warning(_("New attribute column <%s> added to the table"),
752 colname[i]);
753 }
754
755 Ogr_field = OGR_Fld_Create(colname[i], ogr_ftype);
756 if (ogr_ftype == OFTString && colwidth > 0)
757 OGR_Fld_SetWidth(Ogr_field, colwidth);
758 if (OGR_L_CreateField(Ogr_layer, Ogr_field, 0) != OGRERR_NONE)
759 G_fatal_error(_("Unable to create column <%s>"),
760 colname[i]);
761
762 OGR_Fld_Destroy(Ogr_field);
763 }
764 if (keycol == -1)
765 G_fatal_error(_("Key column <%s> not found"), Fi->key);
766 }
767 }
768
769 Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
770
771 n_feat = n_nocat = n_noatt = 0;
772
773 if (OGR_L_TestCapability(Ogr_layer, OLCTransactions))
774 OGR_L_StartTransaction(Ogr_layer);
775
776 /* export polygons oriented according to OGC simple features standard 1.2.1
777 * outer rings are oriented counter-clockwise (CCW)
778 * inner rings are oriented clockwise (CW) */
779 outer_ring_ccw = 1;
780 /* some formats expect outer rings to be CW and inner rings to be CCW:
781 * ESRI Shapefile, PGeo, FileGDB, OpenFileGDB (all ESRI) */
782 if (strcmp(options.format->answer, "ESRI_Shapefile") == 0 ||
783 strcmp(options.format->answer, "PGeo") == 0 ||
784 strcmp(options.format->answer, "FileGDB") == 0 ||
785 strcmp(options.format->answer, "OpenFileGDB") == 0) {
786 outer_ring_ccw = 0;
787 }
788 G_debug(1, "Format \"%s\", outer ring %s",
789 options.format->answer, (outer_ring_ccw ? "CCW" : "CW"));
790
791 /* Lines (run always to count features of different type) */
792 if (otype & (GV_POINTS | GV_LINES | GV_KERNEL | GV_FACE)) {
793 G_message(n_("Exporting %d feature...",
794 "Exporting %d features...",
795 Vect_get_num_primitives(&In, otype)),
796 Vect_get_num_primitives(&In, otype));
797
798 n_feat += export_lines(&In, field, otype, flags.multi->answer ? TRUE : FALSE,
799 donocat, ftype == GV_BOUNDARY ? TRUE : FALSE,
800 Ogr_featuredefn, Ogr_layer,
801 Fi, Driver, ncol, colctype,
802 colname, doatt, flags.nocat->answer ? TRUE : FALSE,
803 &n_noatt, &n_nocat);
804 }
805
806 /* Areas (run always to count features of different type) */
807 if (Vect_get_num_areas(&In) > 0 && (otype & GV_AREA)) {
808 G_message(n_("Exporting %d area (may take some time)...",
809 "Exporting %d areas (may take some time)...",
810 Vect_get_num_areas(&In)),
811 Vect_get_num_areas(&In));
812
813 n_feat += export_areas(&In, field, flags.multi->answer ? TRUE : FALSE, donocat,
814 Ogr_featuredefn, Ogr_layer,
815 Fi, Driver, ncol, colctype,
816 colname, doatt, flags.nocat->answer ? TRUE : FALSE,
817 &n_noatt, &n_nocat, outer_ring_ccw);
818 }
819
820 /*
821 TODO: Volumes. Do not export kernels here, that's already done.
822 We do need to worry about holes, though. NOTE: We can probably
823 just merge this with faces export function. Except for GRASS,
824 which output format would know the difference?
825 */
826 if (Vect_get_num_volumes(&In) > 0 && (otype & GV_VOLUME)) {
827 G_message(n_("Exporting %d volume...",
828 "Exporting %d volumes...",
829 Vect_get_num_volumes(&In)),
830 Vect_get_num_volumes(&In));
831 G_warning(_("Export of volumes not implemented yet. Skipping."));
832 }
833
834 if (OGR_L_TestCapability(Ogr_layer, OLCTransactions))
835 OGR_L_CommitTransaction(Ogr_layer);
836
837 ds_close(hDS);
838
839 Vect_close(&In);
840
841 if (doatt) {
842 db_close_database(Driver);
843 db_shutdown_driver(Driver);
844 }
845
846 /* Summary */
847 if (n_noatt > 0)
848 G_important_message(n_("%d feature without attributes was written",
849 "%d features without attributes were written",
850 n_noatt), n_noatt);
851
852 if (n_nocat > 0) {
853 if (donocat)
854 G_important_message(n_("%d feature without category was written",
855 "%d features without category were written",
856 n_nocat), n_nocat);
857 else
858 G_warning(n_("%d feature without category was skipped. "
859 "Features without category are written only when -%c flag is given.",
860 "%d features without category were skipped. "
861 "Features without category are written only when -%c flag is given.",
862 n_nocat), n_nocat, flags.cat->key);
863 }
864
865 /* Enable this? May be confusing that for area type are not
866 * reported all boundaries/centroids. OTOH why should be
867 * reported? */
868 /*
869 if (((otype & GV_POINTS) || (otype & GV_LINES)) && fskip > 0)
870 G_warning ("%d features of different type skip", fskip);
871 */
872
873 if (n_feat < 1)
874 G_warning(_("Output layer is empty, no features written"));
875 G_done_msg(n_("%d feature (%s type) written to <%s> (%s format).",
876 "%d features (%s type) written to <%s> (%s format).",
877 n_feat), n_feat,
878 OGRGeometryTypeToName(wkbtype),
879 options.layer->answer, options.format->answer);
880
881 exit(EXIT_SUCCESS);
882}
Note: See TracBrowser for help on using the repository browser.