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