GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
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#include <ogr_api.h>
37
38#ifdef HAVE_POSTGRES
39#include "pg_local_proto.h"
40#endif
41
42static int check_sftype(const struct line_pnts *, int, SF_FeatureType, int);
43static int get_sftype(const struct line_pnts *, int, int);
44static void print_point(const struct line_pnts *, int, int, int, FILE *);
45
46/*!
47 \brief Get SF type of given vector feature
48
49 List of supported feature types:
50 - GV_POINT -> SF_POINT
51 - GV_LINE -> SF_LINESTRING
52 - GV_LINE (closed) -> SF_LINEARRING
53 - GV_BOUNDARY -> SF_POLYGON
54
55 \param Points pointer to line_pnts structure
56 \param type feature type (see supported types above)
57 \param with_z WITH_Z for 3D data
58
59 \return SF type identificator (see list of supported types)
60 \return -1 on error
61 */
62SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type,
63 int with_z)
64{
65 return get_sftype(Points, type, with_z);
66}
67
68/*!
69 \brief Get relevant GV type
70
71 \param sftype SF geometry type (SF_POINT, SF_LINESTRING, ...)
72
73 \return GV type
74 \return -1 on error
75 */
77{
78 switch (sftype) {
79 case SF_POINT:
80 case SF_POINT25D:
81 return GV_POINT;
82 case SF_LINESTRING:
84 case SF_LINEARRING:
85 return GV_LINE;
86 case SF_POLYGON:
87 case SF_POLYGON25D:
88 return GV_BOUNDARY;
89 default:
90 break;
91 }
92
93 return -1;
94}
95
96/*!
97 \brief Check SF type
98
99 E.g. if <em>type</em> is GV_LINE with two or more segments and the
100 start node is identical with the end node, and <em>sftype</em> is
101 SF_LINEARRING, functions returns 1, otherwise 0.
102
103 \param Points pointer to line_pnts structure
104 \param type feature type (GV_POINT, GV_LINE, ...)
105 \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
106 \param with_z non-zero value for 3D data
107
108 \return 1 if type is sftype
109 \return 0 type differs from sftype
110 */
111int Vect_sfa_check_line_type(const struct line_pnts *Points, int type,
112 SF_FeatureType sftype, int with_z)
113{
114 return check_sftype(Points, type, sftype, with_z);
115}
116
117/*!
118 \brief Get geometry dimension
119
120 \param type feature type (GV_POINT, GV_LINE, ...)
121
122 \return 0 for GV_POINT
123 \return 1 for GV_LINE
124 \return 2 for GV_BOUNDARY
125 \return -1 unsupported feature type
126 */
128{
129 if (type == GV_POINT)
130 return 0;
131 if (type == GV_LINE)
132 return 1;
133 if (type == GV_BOUNDARY)
134 return 2;
135
136 return -1;
137}
138
139/*!
140 \brief Get geometry type (string)
141
142 Supported types:
143 - GV_POINT -> SF_POINT -> "POINT"
144 - GV_LINE -> SF_LINESTRING -> "LINESTRING"
145 - GV_LINE (closed) -> SF_LINEARRING -> "LINEARRING"
146 - GV_BOUNDARY (closed) -> SF_POLYGON -> "POLYGON"
147
148 Note: Allocated string should be freed by G_free().
149
150 \param Points pointer to line_pnts structure (feature geometry)
151 \param type feature type (see supported types above)
152
153 \return geometry type string
154 \return NULL unsupported feature type
155 */
156char *Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
157{
159
160 if (sftype == SF_POINT)
161 return G_store("POINT");
162 if (sftype == SF_LINESTRING)
163 return G_store("LINESTRING");
164 if (sftype == SF_LINEARRING)
165 return G_store("LINEARRING");
166 if (sftype == SF_POLYGON)
167 return G_store("POLYGON");
168
169 return NULL;
170}
171
172/*!
173 \brief Export geometry to Well-Known Text
174
175 \param Points pointer to line_pnts structure
176 \param type feature type
177 \param with_z non-zero value for 3D data
178 \param precision floating number precision
179 \param[out] file file where to write the output
180
181 \return 0 on success
182 \return -1 unsupported feature type
183 */
184int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z,
185 int precision, FILE *file)
186{
187 int i, sftype;
188
189 sftype = Vect_sfa_get_line_type(Points, type, with_z);
190
191 switch (sftype) {
192 case SF_POINT: { /* point */
193 fprintf(file, "POINT(");
194 print_point(Points, 0, with_z, precision, file);
195 fprintf(file, ")\n");
196 break;
197 }
198 case SF_LINESTRING:
199 case SF_LINEARRING: /* line */ {
200 if (sftype == SF_LINESTRING)
201 fprintf(file, "LINESTRING(");
202 else
203 fprintf(file, "LINEARRING(");
204 for (i = 0; i < Points->n_points; i++) {
205 print_point(Points, i, with_z, precision, file);
206 if (i < Points->n_points - 1)
207 fprintf(file, ", ");
208 }
209 fprintf(file, ")\n");
210 break;
211 }
212 case SF_POLYGON: /* polygon */ {
213 /* write only outer/inner ring */
214 fprintf(file, "(");
215 for (i = 0; i < Points->n_points; i++) {
216 print_point(Points, i, with_z, precision, file);
217 if (i < Points->n_points - 1)
218 fprintf(file, ", ");
219 }
220 fprintf(file, ")");
221 break;
222 }
223 default: {
224 G_warning(_("Unknown Simple Features type (%d)"), sftype);
225 return -1;
226 }
227 }
228
229 fflush(file);
230 return 0;
231}
232
233/*!
234 \brief Check if feature is simple
235
236 \param Points pointer to line_pnts structure (unused)
237 \param type feature type (GV_POINT, GV_LINE, ...) (unused)
238 \param with_z (unused)
239
240 \return 1 feature simple
241 \return 0 feature not simple
242 \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
243 \note Implementation is pending, now always returns 0
244 */
245int Vect_sfa_is_line_simple(const struct line_pnts *Points UNUSED,
246 int type UNUSED, int with_z UNUSED)
247{
248 /* TODO:
249 SF_FeatureType sftype;
250
251 Vect_sfa_get_line_type(Points, type, with_z);
252
253 */
254
255 return 0;
256}
257
258/*!
259 \brief Check if feature is closed
260
261 \param Points pointer to line_pnts structure
262 \param type feature type (GV_LINE or GV_BOUNDARY)
263 \param with_z
264
265 \return 1 feature closed
266 \return 0 feature not closed
267 \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
268 */
269int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type,
270 int with_z)
271{
272 int npoints;
273
274 if (type & (GV_LINES)) {
275 npoints = Vect_get_num_line_points(Points);
276 if (npoints > 2 && Points->x[0] == Points->x[npoints - 1] &&
277 Points->y[0] == Points->y[npoints - 1]) {
278 if (!with_z)
279 return 1;
280 if (Points->z[0] == Points->z[npoints - 1])
281 return 1;
282 }
283 return 0;
284 }
285 return -1;
286}
287
288/*!
289 \brief Get number of simple features
290
291 For native format or PostGIS Topology returns -1
292
293 \param Map vector map
294
295 \return number of features
296 \return -1 on error
297 */
299{
300 int nfeat;
301
302 nfeat = 0;
303 if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
304 /* OGR */
305 const struct Format_info_ogr *ogr_info;
306
307 ogr_info = &(Map->fInfo.ogr);
308
309 if (!ogr_info->layer)
310 return -1;
311
312 return OGR_L_GetFeatureCount(ogr_info->layer, TRUE);
313 }
314 else if (Map->format == GV_FORMAT_POSTGIS &&
315 !Map->fInfo.pg.toposchema_name) {
316#ifdef HAVE_POSTGRES
317 /* PostGIS */
318 char stmt[DB_SQL_MAX];
319
320 const struct Format_info_pg *pg_info;
321
322 pg_info = &(Map->fInfo.pg);
323
324 if (!pg_info->conn || !pg_info->table_name) {
325 G_warning(_("No connection defined"));
326 return -1;
327 }
328
329 snprintf(stmt, sizeof(stmt), "SELECT count(*) FROM \"%s\".\"%s\"",
330 pg_info->schema_name, pg_info->table_name);
332 if (nfeat < 0) {
333 G_warning(_("Unable to get number of simple features"));
334 return -1;
335 }
336#else
337 G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
338 return -1;
339#endif
340 }
341 else {
342 const char *map_name = Vect_get_full_name(Map);
343 G_warning(_("Unable to report simple features for vector map <%s>"),
344 map_name);
345 G_free((void *)map_name);
346 return -1;
347 }
348
349 return nfeat;
350}
351
352int check_sftype(const struct line_pnts *points, int type,
353 SF_FeatureType sftype, int with_z)
354{
355 if (type == GV_POINT && sftype == SF_POINT) {
356 return 1;
357 }
358
359 if (type == GV_LINE) {
360 if (sftype == SF_LINESTRING)
361 return 1;
362
363 if (sftype == SF_LINEARRING &&
364 Vect_sfa_is_line_closed(points, type, with_z))
365 return 1;
366 }
367
368 if (type == GV_BOUNDARY) {
369 if (sftype == SF_POLYGON &&
370 Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
371 return 1;
372 }
373
374 return 0;
375}
376
377int get_sftype(const struct line_pnts *points, int type, int with_z)
378{
379 if (check_sftype(points, type, SF_POINT, with_z))
380 return SF_POINT;
381
382 if (check_sftype(points, type, SF_LINEARRING, with_z))
383 return SF_LINEARRING;
384
385 if (check_sftype(points, type, SF_LINESTRING, with_z))
386 return SF_LINESTRING;
387
388 if (check_sftype(points, type, SF_POLYGON, with_z))
389 return SF_POLYGON;
390
391 return -1;
392}
393
394void print_point(const struct line_pnts *Points, int index, int with_z,
395 int precision, FILE *file)
396{
397 fprintf(file, "%.*f %.*f", precision, Points->x[index], precision,
398 Points->y[index]);
399 if (with_z)
400 fprintf(file, " %.*f", precision, Points->z[index]);
401}
#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:147
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
int Vect_get_num_line_points(const struct line_pnts *)
Get number of line points.
Definition line.c:267
const char * Vect_get_full_name(struct Map_info *)
Get fully qualified name of vector map.
SF_FeatureType
Simple feature types.
@ SF_POLYGON
@ SF_LINESTRING
@ SF_POLYGON25D
@ SF_POINT25D
@ SF_POINT
@ SF_LINESTRING25D
@ SF_LINEARRING
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition dig_defines.h:89
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_LINES
#define GV_BOUNDARY
#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.
char * Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
Get geometry type (string)
SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type, int with_z)
Get SF type of given vector feature.
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, int type, int with_z)
Check if feature is simple.
int Vect_sfa_get_type(SF_FeatureType sftype)
Get relevant GV type.
Non-native format info (OGR)
Non-native format info (PostGIS)
Vector map info.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.