GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-b35369f6b7
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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  \param with_z
267 
268  \return 1 feature closed
269  \return 0 feature not closed
270  \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
271  */
272 int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type,
273  int with_z)
274 {
275  int npoints;
276 
277  if (type & (GV_LINES)) {
278  npoints = Vect_get_num_line_points(Points);
279  if (npoints > 2 && Points->x[0] == Points->x[npoints - 1] &&
280  Points->y[0] == Points->y[npoints - 1]) {
281  if (!with_z)
282  return 1;
283  if (Points->z[0] == Points->z[npoints - 1])
284  return 1;
285  }
286  return 0;
287  }
288  return -1;
289 }
290 
291 /*!
292  \brief Get number of simple features
293 
294  For native format or PostGIS Topology returns -1
295 
296  \param Map vector map
297 
298  \return number of features
299  \return -1 on error
300  */
302 {
303  int nfeat;
304 
305  nfeat = 0;
306  if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
307  /* OGR */
308 #ifdef HAVE_OGR
309  const struct Format_info_ogr *ogr_info;
310 
311  ogr_info = &(Map->fInfo.ogr);
312 
313  if (!ogr_info->layer)
314  return -1;
315 
316  return OGR_L_GetFeatureCount(ogr_info->layer, TRUE);
317 #else
318  G_fatal_error(_("GRASS is not compiled with OGR support"));
319  return -1;
320 #endif
321  }
322  else if (Map->format == GV_FORMAT_POSTGIS &&
323  !Map->fInfo.pg.toposchema_name) {
324 #ifdef HAVE_POSTGRES
325  /* PostGIS */
326  char stmt[DB_SQL_MAX];
327 
328  const struct Format_info_pg *pg_info;
329 
330  pg_info = &(Map->fInfo.pg);
331 
332  if (!pg_info->conn || !pg_info->table_name) {
333  G_warning(_("No connection defined"));
334  return -1;
335  }
336 
337  snprintf(stmt, sizeof(stmt), "SELECT count(*) FROM \"%s\".\"%s\"",
338  pg_info->schema_name, pg_info->table_name);
339  nfeat = Vect__execute_get_value_pg(pg_info->conn, stmt);
340  if (nfeat < 0) {
341  G_warning(_("Unable to get number of simple features"));
342  return -1;
343  }
344 #else
345  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
346  return -1;
347 #endif
348  }
349  else {
350  const char *map_name = Vect_get_full_name(Map);
351  G_warning(_("Unable to report simple features for vector map <%s>"),
352  map_name);
353  G_free((void *)map_name);
354  return -1;
355  }
356 
357  return nfeat;
358 }
359 
360 int check_sftype(const struct line_pnts *points, int type,
361  SF_FeatureType sftype, int with_z)
362 {
363  if (type == GV_POINT && sftype == SF_POINT) {
364  return 1;
365  }
366 
367  if (type == GV_LINE) {
368  if (sftype == SF_LINESTRING)
369  return 1;
370 
371  if (sftype == SF_LINEARRING &&
372  Vect_sfa_is_line_closed(points, type, with_z))
373  return 1;
374  }
375 
376  if (type == GV_BOUNDARY) {
377  if (sftype == SF_POLYGON &&
378  Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
379  return 1;
380  }
381 
382  return 0;
383 }
384 
385 int get_sftype(const struct line_pnts *points, int type, int with_z)
386 {
387  if (check_sftype(points, type, SF_POINT, with_z))
388  return SF_POINT;
389 
390  if (check_sftype(points, type, SF_LINEARRING, with_z))
391  return SF_LINEARRING;
392 
393  if (check_sftype(points, type, SF_LINESTRING, with_z))
394  return SF_LINESTRING;
395 
396  if (check_sftype(points, type, SF_POLYGON, with_z))
397  return SF_POLYGON;
398 
399  return -1;
400 }
401 
402 void print_point(const struct line_pnts *Points, int index, int with_z,
403  int precision, FILE *file)
404 {
405  fprintf(file, "%.*f %.*f", precision, Points->x[index], precision,
406  Points->y[index]);
407  if (with_z)
408  fprintf(file, " %.*f", precision, Points->z[index]);
409 }
#define NULL
Definition: ccmath.h:32
#define DB_SQL_MAX
Definition: dbmi.h:142
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
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:78
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition: gis.h:46
#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:1599
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