GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-835afb4352
open_ogr.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/open_ogr.c
3 
4  \brief Vector library - Open OGR layer as vector map layer
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2001-2010 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  \author Update to GRASS 7.0 Martin Landa <landa.martin gmail.com> (2009)
16  */
17 
18 #include <unistd.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 
23 #include <grass/vector.h>
24 #include <grass/dbmi.h>
25 #include <grass/glocale.h>
26 
27 #ifdef HAVE_OGR
28 #include <ogr_api.h>
29 #endif
30 
31 /*!
32  \brief Open existing OGR layer on non-topological level
33 
34  Note: Map->name, Map->mapset, Map->fInfo.ogr.dsn and
35  Map->fInfo.ogr.layer_name must be set before.
36 
37  \param[in,out] Map pointer to Map_info structure
38  \param update TRUE for write mode, otherwise read-only
39 
40  \return 0 success
41  \return -1 error
42  */
43 int V1_open_old_ogr(struct Map_info *Map, int update)
44 {
45 #ifdef HAVE_OGR
46  int i, layer, nLayers;
47 
48  struct Format_info_ogr *ogr_info;
49 
50  OGRDataSourceH Ogr_ds;
51  OGRLayerH Ogr_layer;
52  OGRFeatureDefnH Ogr_featuredefn;
53  OGRwkbGeometryType Ogr_geom_type;
54 
55  Ogr_layer = NULL;
56  Ogr_geom_type = wkbUnknown;
57 
58  ogr_info = &(Map->fInfo.ogr);
59  if (!ogr_info->dsn) {
60  G_fatal_error(_("OGR datasource not defined"));
61  return -1;
62  }
63 
64  if (!ogr_info->layer_name) {
65  G_fatal_error(_("OGR layer not defined"));
66  return -1;
67  }
68 
69  G_debug(2, "V1_open_old_ogr(): dsn = %s layer = %s", ogr_info->dsn,
70  ogr_info->layer_name);
71 
72  OGRRegisterAll();
73 
74  /* open data source handle */
75  Ogr_ds = OGROpen(ogr_info->dsn, FALSE, NULL);
76  if (Ogr_ds == NULL)
77  G_fatal_error(_("Unable to open OGR data source '%s'"), ogr_info->dsn);
78  ogr_info->ds = Ogr_ds;
79 
80  /* get layer number */
81  layer = -1;
82  nLayers = OGR_DS_GetLayerCount(Ogr_ds);
83  G_debug(2, "%d layers found in data source", nLayers);
84 
85  for (i = 0; i < nLayers; i++) {
86  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
87  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
88  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), ogr_info->layer_name) ==
89  0) {
90  Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
91  layer = i;
92  break;
93  }
94  }
95  if (layer == -1) {
96  OGR_DS_Destroy(Ogr_ds);
97  G_fatal_error(_("OGR layer <%s> not found"), ogr_info->layer_name);
98  }
99  G_debug(2, "OGR layer %d opened", layer);
100 
101  ogr_info->layer = Ogr_layer;
102  if (update && OGR_L_TestCapability(ogr_info->layer, OLCTransactions) &&
103  (OGR_L_StartTransaction(ogr_info->layer) != OGRERR_NONE)) {
104  OGR_DS_Destroy(Ogr_ds);
105  G_warning(_("OGR transaction with layer <%s> failed to start"),
106  ogr_info->layer_name);
107  return -1;
108  }
109 
110  switch (Ogr_geom_type) {
111  case wkbPoint25D:
112  case wkbLineString25D:
113  case wkbPolygon25D:
114  case wkbMultiPoint25D:
115  case wkbMultiLineString25D:
116  case wkbMultiPolygon25D:
117  case wkbGeometryCollection25D:
118  Map->head.with_z = WITH_Z;
119  break;
120  default:
121  Map->head.with_z = WITHOUT_Z;
122  break;
123  }
124 
125  ogr_info->cache.fid = -1; /* FID >= 0 */
126 
127  return 0;
128 #else
129  G_fatal_error(_("GRASS is not compiled with OGR support"));
130  return -1;
131 #endif
132 }
133 
134 /*!
135  \brief Open existing OGR layer on topological level
136 
137  This functions reads feature index (fidx) file required for
138  pseudo-topology.
139 
140  \param[in,out] Map pointer to Map_info structure
141 
142  \return 0 success
143  \return -1 error
144  */
145 int V2_open_old_ogr(struct Map_info *Map)
146 {
147 #ifdef HAVE_OGR
148 
149  G_debug(3, "V2_open_old_ogr(): name = %s mapset = %s", Map->name,
150  Map->mapset);
151 
152  if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) {
153  G_warning(_("Unable to open feature index file for vector map <%s>"),
154  Vect_get_full_name(Map));
155  G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset));
156  }
157 
158  Map->fInfo.ogr.next_line = 1; /* reset feature cache */
159 
160  return 0;
161 #else
162  G_fatal_error(_("GRASS is not compiled with OGR support"));
163  return -1;
164 #endif
165 }
166 
167 /*!
168  \brief Prepare OGR datasource for creating new OGR layer (level 1)
169 
170  New OGR layer is created when writing features by
171  Vect_wrile_line().
172 
173  \param[out] Map pointer to Map_info structure
174  \param name name of OGR layer to create
175  \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
176 
177  \return 0 success
178  \return -1 error
179  */
180 int V1_open_new_ogr(struct Map_info *Map, const char *name, int with_z)
181 {
182 #ifdef HAVE_OGR
183  int i, nlayers;
184 
185  struct Format_info_ogr *ogr_info;
186 
187  OGRSFDriverH Ogr_driver;
188  OGRDataSourceH Ogr_ds;
189  OGRLayerH Ogr_layer;
190  OGRFeatureDefnH Ogr_featuredefn;
191 
192  OGRRegisterAll();
193 
194  ogr_info = &(Map->fInfo.ogr);
195 
196  G_debug(1, "V1_open_new_ogr(): name = %s with_z = %d", name, with_z);
197  Ogr_driver = OGRGetDriverByName(ogr_info->driver_name);
198  if (!Ogr_driver) {
199  G_warning(_("Unable to get OGR driver <%s>"), ogr_info->driver_name);
200  return -1;
201  }
202  ogr_info->driver = Ogr_driver;
203 
204  /* TODO: creation options */
205  Ogr_ds = OGR_Dr_CreateDataSource(Ogr_driver, ogr_info->dsn, NULL);
206  if (!Ogr_ds) {
207  G_warning(_("Unable to create OGR data source '%s'"), ogr_info->dsn);
208  return -1;
209  }
210  ogr_info->ds = Ogr_ds;
211 
212  nlayers = OGR_DS_GetLayerCount(Ogr_ds);
213  for (i = 0; i < nlayers; i++) {
214  Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
215  Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
216  if (strcmp(OGR_FD_GetName(Ogr_featuredefn), name) == 0) {
217  if (G_get_overwrite()) {
218  G_warning(
219  _("OGR layer <%s> already exists and will be overwritten"),
220  ogr_info->layer_name);
221 
222  if (OGR_DS_DeleteLayer(Ogr_ds, i) != OGRERR_NONE) {
223  G_warning(_("Unable to delete OGR layer <%s>"),
224  ogr_info->layer_name);
225  return -1;
226  }
227  }
228  else {
230  _("OGR layer <%s> already exists in datasource '%s'"),
231  ogr_info->layer_name, ogr_info->dsn);
232  }
233  ogr_info->layer = NULL;
234  break;
235  }
236  }
237 
238  return 0;
239 #else
240  G_fatal_error(_("GRASS is not compiled with OGR support"));
241  return -1;
242 #endif
243 }
244 
245 /*!
246  \brief Open feature index file
247 
248  \param[in,out] Map pointer to Map_info struct
249  \param[out] offset pointer to Format_info_offset (OGR or PG)
250 
251  \return 0 on success
252  \return -1 on error
253  */
255 {
256  char elem[GPATH_MAX];
257  char buf[5]; /* used for format version */
258  long length;
259  int Version_Major, Version_Minor, Back_Major, Back_Minor, byte_order;
260 
261  struct gvfile fp;
262  struct Port_info port;
263 
264  G_debug(1, "Vect_open_fidx(): name = %s mapset = %s format = %d", Map->name,
265  Map->mapset, Map->format);
266 
267  sprintf(elem, "%s/%s", GV_DIRECTORY, Map->name);
268  dig_file_init(&fp);
269  fp.file = G_fopen_old(elem, GV_FIDX_ELEMENT, Map->mapset);
270  if (fp.file == NULL) {
271  G_debug(1, "unable to open fidx file for vector map <%s>",
272  Vect_get_full_name(Map));
273  return -1;
274  }
275 
276  /* Header */
277  if (0 >= dig__fread_port_C(buf, 5, &fp))
278  return -1;
279  Version_Major = buf[0];
280  Version_Minor = buf[1];
281  Back_Major = buf[2];
282  Back_Minor = buf[3];
283  byte_order = buf[4];
284 
285  /* check version numbers */
286  if (Version_Major > 5 || Version_Minor > 0) {
287  if (Back_Major > 5 || Back_Minor > 0) {
288  G_fatal_error(_("Feature index format version %d.%d is not "
289  "supported by this release."
290  " Try to rebuild topology or upgrade GRASS."),
291  Version_Major, Version_Minor);
292  return -1;
293  }
294  G_warning(_("Your GRASS version does not fully support feature index "
295  "format %d.%d of the vector."
296  " Consider to rebuild topology or upgrade GRASS."),
297  Version_Major, Version_Minor);
298  }
299 
301  dig_set_cur_port(&port);
302 
303  /* Body */
304  /* bytes 6 - 9 : header size */
305  if (0 >= dig__fread_port_L(&length, 1, &fp))
306  return -1;
307  G_debug(4, " header size %ld", length);
308 
309  G_fseek(fp.file, length, SEEK_SET);
310 
311  /* number of records */
312  if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp))
313  return -1;
314 
315  /* alloc space */
316  offset->array = (int *)G_malloc(offset->array_num * sizeof(int));
317  offset->array_alloc = offset->array_num;
318 
319  /* offsets */
320  if (0 >= dig__fread_port_I(offset->array, offset->array_num, &fp))
321  return -1;
322 
323  fclose(fp.file);
324 
325  G_debug(3, "%d records read from fidx", offset->array_num);
326 
327  return 0;
328 }
#define NULL
Definition: ccmath.h:32
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:251
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
int G_get_overwrite(void)
Get overwrite value.
Definition: parser.c:957
int G_debug(int, const char *,...) __attribute__((format(printf
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
#define GV_DIRECTORY
Name of vector directory.
Definition: dig_defines.h:8
#define WITH_Z
Definition: dig_defines.h:172
#define GV_FIDX_ELEMENT
External format (OGR), feature index.
Definition: dig_defines.h:26
#define WITHOUT_Z
2D/3D vector data
Definition: dig_defines.h:171
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:900
int dig__fread_port_L(long *, size_t, struct gvfile *)
Read longs from the Portable Vector Format.
Definition: portable.c:262
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:996
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:511
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:345
void dig_file_init(struct gvfile *file)
Initialize gvfile structure.
Definition: file.c:171
#define GPATH_MAX
Definition: gis.h:194
#define FALSE
Definition: gis.h:83
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
int V1_open_new_ogr(struct Map_info *Map, const char *name, int with_z)
Prepare OGR datasource for creating new OGR layer (level 1)
Definition: open_ogr.c:180
int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset)
Open feature index file.
Definition: open_ogr.c:254
int V2_open_old_ogr(struct Map_info *Map)
Open existing OGR layer on topological level.
Definition: open_ogr.c:145
int V1_open_old_ogr(struct Map_info *Map, int update)
Open existing OGR layer on non-topological level.
Definition: open_ogr.c:43
long fid
Feature id.
Definition: dig_structs.h:486
Data structure used for building pseudo-topology.
Definition: dig_structs.h:388
int * array
Offset list.
Definition: dig_structs.h:436
int array_alloc
Space allocated for offset list.
Definition: dig_structs.h:444
int array_num
Number of items in offset list.
Definition: dig_structs.h:440
Non-native format info (OGR)
Definition: dig_structs.h:505
char * dsn
OGR datasource name.
Definition: dig_structs.h:513
OGRSFDriverH driver
Pointer to OGRDriver.
Definition: dig_structs.h:526
char * driver_name
OGR driver name.
Definition: dig_structs.h:509
OGRDataSourceH ds
Pointer to OGRDataSource.
Definition: dig_structs.h:530
char * layer_name
OGR layer name.
Definition: dig_structs.h:517
int next_line
Next line to be read.
Definition: dig_structs.h:584
OGRLayerH layer
Pointer to OGRLayer.
Definition: dig_structs.h:534
struct Format_info_offset offset
Offset list used for building pseudo-topology.
Definition: dig_structs.h:577
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:561
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:708
Vector map info.
Definition: dig_structs.h:1243
char * mapset
Mapset name.
Definition: dig_structs.h:1320
struct dig_head head
Header info.
Definition: dig_structs.h:1388
char * name
Map name (for 4.0)
Definition: dig_structs.h:1316
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1255
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1400
Portability info.
Definition: dig_structs.h:181
int byte_order
File byte order.
Definition: dig_structs.h:185
int with_z
2D/3D vector data
Definition: dig_structs.h:339
File definition.
Definition: dig_structs.h:94
FILE * file
File descriptor.
Definition: dig_structs.h:98