GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-6805375e1b
simple_features.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/simple_features.c
3 
4  \brief Vector library - OGC Simple Features Access
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  Note: <b>In progress!</b> Currently on GV_POINT, GV_LINE,
9  GV_BOUNDARY are supported.
10 
11  \todo
12  - Vect_sfa_line_is_simple()
13  - Vect_sfa_line_srid()
14  - Vect_sfa_line_envelope()
15  - Vect_sfa_line_asbinary()
16  - Vect_sfa_line_is_empty()
17  - Vect_sfa_line_is_3d()
18  - Vect_sfa_line_is_measured()
19  - Vect_sfa_line_boundary()
20 
21  Reference: http://www.opengeospatial.org/standards/sfa
22 
23  (C) 2009, 2011-2013 by the GRASS Development Team
24 
25  This program is free software under the GNU General Public License
26  (>=v2). Read the file COPYING that comes with GRASS for details.
27 
28  \author Martin Landa <landa.martin gmail.com>
29  */
30 
31 #include <stdio.h>
32 
33 #include <grass/vector.h>
34 #include <grass/glocale.h>
35 
36 #ifdef HAVE_POSTGRES
37 #include "pg_local_proto.h"
38 #endif
39 
40 #ifdef HAVE_OGR
41 #include <ogr_api.h>
42 #endif
43 
44 static int check_sftype(const struct line_pnts *, int, SF_FeatureType, int);
45 static int get_sftype(const struct line_pnts *, int, int);
46 static void print_point(const struct line_pnts *, int, int, int, FILE *);
47 
48 /*!
49  \brief Get SF type of given vector feature
50 
51  List of supported feature types:
52  - GV_POINT -> SF_POINT
53  - GV_LINE -> SF_LINESTRING
54  - GV_LINE (closed) -> SF_LINEARRING
55  - GV_BOUNDARY -> SF_POLYGON
56 
57  \param Points pointer to line_pnts structure
58  \param type feature type (see supported types above)
59  \param with_z WITH_Z for 3D data
60 
61  \return SF type identificator (see list of supported types)
62  \return -1 on error
63  */
64 SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type,
65  int with_z)
66 {
67  return get_sftype(Points, type, with_z);
68 }
69 
70 /*!
71  \brief Get relevant GV type
72 
73  \param Map pointer to Map_info structure
74  \param type SF geometry type (SF_POINT, SF_LINESTRING, ...)
75 
76  \return GV type
77  \return -1 on error
78  */
80 {
81  switch (sftype) {
82  case SF_POINT:
83  case SF_POINT25D:
84  return GV_POINT;
85  case SF_LINESTRING:
86  case SF_LINESTRING25D:
87  case SF_LINEARRING:
88  return GV_LINE;
89  case SF_POLYGON:
90  case SF_POLYGON25D:
91  return GV_BOUNDARY;
92  default:
93  break;
94  }
95 
96  return -1;
97 }
98 
99 /*!
100  \brief Check SF type
101 
102  E.g. if <em>type</em> is GV_LINE with two or more segments and the
103  start node is identical with the end node, and <em>sftype</em> is
104  SF_LINEARRING, functions returns 1, otherwise 0.
105 
106  \param Points pointer to line_pnts structure
107  \param type feature type (GV_POINT, GV_LINE, ...)
108  \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
109  \param with_z non-zero value for 3D data
110 
111  \return 1 if type is sftype
112  \return 0 type differs from sftype
113  */
114 int Vect_sfa_check_line_type(const struct line_pnts *Points, int type,
115  SF_FeatureType sftype, int with_z)
116 {
117  return check_sftype(Points, type, sftype, with_z);
118 }
119 
120 /*!
121  \brief Get geometry dimension
122 
123  \param Points pointer to line_pnts structure
124  \param type feature type (GV_POINT, GV_LINE, ...)
125 
126  \return 0 for GV_POINT
127  \return 1 for GV_LINE
128  \return 2 for GV_BOUNDARY
129  \return -1 unsupported feature type
130  */
132 {
133  if (type == GV_POINT)
134  return 0;
135  if (type == GV_LINE)
136  return 1;
137  if (type == GV_BOUNDARY)
138  return 2;
139 
140  return -1;
141 }
142 
143 /*!
144  \brief Get geometry type (string)
145 
146  Supported types:
147  - GV_POINT -> SF_POINT -> "POINT"
148  - GV_LINE -> SF_LINESTRING -> "LINESTRING"
149  - GV_LINE (closed) -> SF_LINEARRING -> "LINEARRING"
150  - GV_BOUNDARY (closed) -> SF_POLYGON -> "POLYGON"
151 
152  Note: Allocated string should be freed by G_free().
153 
154  \param Points pointer to line_pnts structure (feature geometry)
155  \param type feature type (see supported types above)
156 
157  \return geometry type string
158  \return NULL unsupported feature type
159  */
160 char *Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
161 {
162  SF_FeatureType sftype = Vect_sfa_get_line_type(Points, type, 0);
163 
164  if (sftype == SF_POINT)
165  return G_store("POINT");
166  if (sftype == SF_LINESTRING)
167  return G_store("LINESTRING");
168  if (sftype == SF_LINEARRING)
169  return G_store("LINEARRING");
170  if (sftype == SF_POLYGON)
171  return G_store("POLYGON");
172 
173  return NULL;
174 }
175 
176 /*!
177  \brief Export geometry to Well-Known Text
178 
179  \param Points pointer to line_pnts structure
180  \param type feature type
181  \param with_z non-zero value for 3D data
182  \param precision floating number precision
183  \param[out] file file where to write the output
184 
185  \return 0 on success
186  \return -1 unsupported feature type
187  */
188 int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z,
189  int precision, FILE *file)
190 {
191  int i, sftype;
192 
193  sftype = Vect_sfa_get_line_type(Points, type, with_z);
194 
195  switch (sftype) {
196  case SF_POINT: { /* point */
197  fprintf(file, "POINT(");
198  print_point(Points, 0, with_z, precision, file);
199  fprintf(file, ")\n");
200  break;
201  }
202  case SF_LINESTRING:
203  case SF_LINEARRING: /* line */ {
204  if (sftype == SF_LINESTRING)
205  fprintf(file, "LINESTRING(");
206  else
207  fprintf(file, "LINEARRING(");
208  for (i = 0; i < Points->n_points; i++) {
209  print_point(Points, i, with_z, precision, file);
210  if (i < Points->n_points - 1)
211  fprintf(file, ", ");
212  }
213  fprintf(file, ")\n");
214  break;
215  }
216  case SF_POLYGON: /* polygon */ {
217  /* write only outer/inner ring */
218  fprintf(file, "(");
219  for (i = 0; i < Points->n_points; i++) {
220  print_point(Points, i, with_z, precision, file);
221  if (i < Points->n_points - 1)
222  fprintf(file, ", ");
223  }
224  fprintf(file, ")");
225  break;
226  }
227  default: {
228  G_warning(_("Unknown Simple Features type (%d)"), sftype);
229  return -1;
230  }
231  }
232 
233  fflush(file);
234  return 0;
235 }
236 
237 /*!
238  \brief Check if feature is simple
239 
240  \param Points pointer to line_pnts structure
241  \param type feature type (GV_POINT, GV_LINE, ...)
242 
243  \return 1 feature simple
244  \return 0 feature not simple
245  \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
246  \note Implementation is pending, now always returns 0
247  */
248 int Vect_sfa_is_line_simple(const struct line_pnts *Points UNUSED,
249  int type UNUSED, int with_z UNUSED)
250 {
251  /* TODO:
252  SF_FeatureType sftype;
253 
254  Vect_sfa_get_line_type(Points, type, with_z);
255 
256  */
257 
258  return 0;
259 }
260 
261 /*!
262  \brief Check if feature is closed
263 
264  \param Points pointer to line_pnts structure
265  \param type feature type (GV_LINE or GV_BOUNDARY)
266 
267  \return 1 feature closed
268  \return 0 feature not closed
269  \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
270  */
271 int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type,
272  int with_z)
273 {
274  int npoints;
275 
276  if (type & (GV_LINES)) {
277  npoints = Vect_get_num_line_points(Points);
278  if (npoints > 2 && Points->x[0] == Points->x[npoints - 1] &&
279  Points->y[0] == Points->y[npoints - 1]) {
280  if (!with_z)
281  return 1;
282  if (Points->z[0] == Points->z[npoints - 1])
283  return 1;
284  }
285  return 0;
286  }
287  return -1;
288 }
289 
290 /*!
291  \brief Get number of simple features
292 
293  For native format or PostGIS Topology returns -1
294 
295  \param Map vector map
296 
297  \return number of features
298  \return -1 on error
299  */
301 {
302  int nfeat;
303 
304  nfeat = 0;
305  if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
306  /* OGR */
307 #ifdef HAVE_OGR
308  const struct Format_info_ogr *ogr_info;
309 
310  ogr_info = &(Map->fInfo.ogr);
311 
312  if (!ogr_info->layer)
313  return -1;
314 
315  return OGR_L_GetFeatureCount(ogr_info->layer, TRUE);
316 #else
317  G_fatal_error(_("GRASS is not compiled with OGR support"));
318  return -1;
319 #endif
320  }
321  else if (Map->format == GV_FORMAT_POSTGIS &&
322  !Map->fInfo.pg.toposchema_name) {
323 #ifdef HAVE_POSTGRES
324  /* PostGIS */
325  char stmt[DB_SQL_MAX];
326 
327  const struct Format_info_pg *pg_info;
328 
329  pg_info = &(Map->fInfo.pg);
330 
331  if (!pg_info->conn || !pg_info->table_name) {
332  G_warning(_("No connection defined"));
333  return -1;
334  }
335 
336  sprintf(stmt, "SELECT count(*) FROM \"%s\".\"%s\"",
337  pg_info->schema_name, pg_info->table_name);
338  nfeat = Vect__execute_get_value_pg(pg_info->conn, stmt);
339  if (nfeat < 0) {
340  G_warning(_("Unable to get number of simple features"));
341  return -1;
342  }
343 #else
344  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
345  return -1;
346 #endif
347  }
348  else {
349  G_warning(_("Unable to report simple features for vector map <%s>"),
350  Vect_get_full_name(Map));
351  return -1;
352  }
353 
354  return nfeat;
355 }
356 
357 int check_sftype(const struct line_pnts *points, int type,
358  SF_FeatureType sftype, int with_z)
359 {
360  if (type == GV_POINT && sftype == SF_POINT) {
361  return 1;
362  }
363 
364  if (type == GV_LINE) {
365  if (sftype == SF_LINESTRING)
366  return 1;
367 
368  if (sftype == SF_LINEARRING &&
369  Vect_sfa_is_line_closed(points, type, with_z))
370  return 1;
371  }
372 
373  if (type == GV_BOUNDARY) {
374  if (sftype == SF_POLYGON &&
375  Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
376  return 1;
377  }
378 
379  return 0;
380 }
381 
382 int get_sftype(const struct line_pnts *points, int type, int with_z)
383 {
384  if (check_sftype(points, type, SF_POINT, with_z))
385  return SF_POINT;
386 
387  if (check_sftype(points, type, SF_LINEARRING, with_z))
388  return SF_LINEARRING;
389 
390  if (check_sftype(points, type, SF_LINESTRING, with_z))
391  return SF_LINESTRING;
392 
393  if (check_sftype(points, type, SF_POLYGON, with_z))
394  return SF_POLYGON;
395 
396  return -1;
397 }
398 
399 void print_point(const struct line_pnts *Points, int index, int with_z,
400  int precision, FILE *file)
401 {
402  fprintf(file, "%.*f %.*f", precision, Points->x[index], precision,
403  Points->y[index]);
404  if (with_z)
405  fprintf(file, " %.*f", precision, Points->z[index]);
406 }
#define NULL
Definition: ccmath.h:32
#define DB_SQL_MAX
Definition: dbmi.h:142
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
int Vect_get_num_line_points(const struct line_pnts *)
Get number of line points.
Definition: line.c:267
SF_FeatureType
Simple feature types.
Definition: dig_defines.h:239
@ SF_POLYGON
Definition: dig_defines.h:244
@ SF_LINESTRING
Definition: dig_defines.h:242
@ SF_POLYGON25D
Definition: dig_defines.h:256
@ SF_POINT25D
Definition: dig_defines.h:254
@ SF_POINT
Definition: dig_defines.h:241
@ SF_LINESTRING25D
Definition: dig_defines.h:255
@ SF_LINEARRING
Definition: dig_defines.h:253
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
#define GV_LINE
Definition: dig_defines.h:184
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:183
#define GV_LINES
Definition: dig_defines.h:193
#define GV_BOUNDARY
Definition: dig_defines.h:185
#define GV_FORMAT_OGR_DIRECT
OGR format (direct access)
Definition: dig_defines.h:87
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
#define TRUE
Definition: gis.h:79
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:47
#define _(str)
Definition: glocale.h:10
#define file
int Vect__execute_get_value_pg(PGconn *conn, const char *stmt)
Execute SQL statement and get value.
Definition: read_pg.c:1596
int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z, int precision, FILE *file)
Export geometry to Well-Known Text.
SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type, int with_z)
Get SF type of given vector feature.
char * Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
Get geometry type (string)
int Vect_sfa_check_line_type(const struct line_pnts *Points, int type, SF_FeatureType sftype, int with_z)
Check SF type.
int Vect_sfa_get_num_features(struct Map_info *Map)
Get number of simple features.
int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type, int with_z)
Check if feature is closed.
int Vect_sfa_line_dimension(int type)
Get geometry dimension.
int Vect_sfa_is_line_simple(const struct line_pnts *Points UNUSED, int type UNUSED, int with_z UNUSED)
Check if feature is simple.
int Vect_sfa_get_type(SF_FeatureType sftype)
Get relevant GV type.
Non-native format info (OGR)
Definition: dig_structs.h:505
OGRLayerH layer
Pointer to OGRLayer.
Definition: dig_structs.h:534
Non-native format info (PostGIS)
Definition: dig_structs.h:590
char * schema_name
Schema name.
Definition: dig_structs.h:602
PGconn * conn
PGconn object (generated by PQconnectdb)
Definition: dig_structs.h:650
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:686
char * table_name
Table name.
Definition: dig_structs.h:606
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:712
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:708
Vector map info.
Definition: dig_structs.h:1243
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
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
double * y
Array of Y coordinates.
Definition: dig_structs.h:1659
double * x
Array of X coordinates.
Definition: dig_structs.h:1655
int n_points
Number of points.
Definition: dig_structs.h:1667
double * z
Array of Z coordinates.
Definition: dig_structs.h:1663