GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
write_sfa.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/write_sfa.c
3
4 \brief Vector library - write vector feature - simple feature access (level
5 2)
6
7 Higher level functions for reading/writing/manipulating vectors.
8
9 See write_ogr.c (OGR interface) and write_pg.c (PostGIS interface)
10 for implementation issues.
11
12 \todo SFA version of V2__delete_area_cats_from_cidx_nat()
13 \todo function to delete corresponding entry in fidx
14 \todo SFA version of V2__add_area_cats_to_cidx_nat
15 \todo SFA version of V2__add_line_to_topo_nat
16
17 SPDX-FileCopyrightText: 2011-2012 Martin Landa
18 SPDX-FileCopyrightText: GRASS Development Team
19 SPDX-License-Identifier: GPL-2.0-or-later
20
21 \author Martin Landa <landa.martin gmail.com>
22 */
23
24#include <grass/vector.h>
25#include <grass/glocale.h>
26
27#include "local_proto.h"
28
29#ifdef HAVE_POSTGRES
30#include "pg_local_proto.h"
31#endif
32
33static void V2__add_line_to_topo_sfa(struct Map_info *, int,
34 const struct line_pnts *,
35 const struct line_cats *);
36
37/*!
38 \brief Writes feature on level 2 (OGR/PostGIS interface, pseudo-topological
39 level)
40
41 \param Map pointer to Map_info structure
42 \param type feature type (see V1_write_line_ogr() for list of supported
43 types) \param points pointer to line_pnts structure (feature geometry) \param
44 cats pointer to line_cats structure (feature categories)
45
46 \return feature index in offset array (related to pseudo-topology)
47 \return -1 on error
48 */
50 const struct line_pnts *points,
51 const struct line_cats *cats)
52{
53 int line;
54 off_t offset;
55 struct Plus_head *plus;
56 struct bound_box box;
58
59 line = 0;
60 plus = &(Map->plus);
61
62 G_debug(3, "V2_write_line_sfa(): type = %d (format = %d)", type,
63 Map->format);
64
65 if (Map->format == GV_FORMAT_POSTGIS) {
66 offset_info = &(Map->fInfo.pg.offset);
67 offset = V1_write_line_pg(Map, type, points, cats);
68 }
69 else {
70 offset_info = &(Map->fInfo.pg.offset);
71 offset = V1_write_line_ogr(Map, type, points, cats);
72 }
73 if (offset < 0)
74 return -1;
75
76 if (!(plus->update_cidx)) {
77 plus->cidx_up_to_date = FALSE; /* category index will be outdated */
78 }
79
80 /* Update topology */
81 if (plus->built >= GV_BUILD_BASE) {
82 dig_line_box(points, &box);
83 line = dig_add_line(plus, type, points, &box, offset);
84 G_debug(3, "\tline added to topo with line = %d", line);
85 if (line == 1)
86 Vect_box_copy(&(plus->box), &box);
87 else
88 Vect_box_extend(&(plus->box), &box);
89
90 if (type == GV_BOUNDARY) {
91 int ret, cline;
92 long fid;
93 double x, y;
94
95 struct bound_box box;
96 struct line_pnts *CPoints;
97
98 /* add virtual centroid to pseudo-topology */
99 ret = Vect_get_point_in_poly(points, &x, &y);
100 if (ret == 0) {
103
104 fid = offset_info->array[offset];
105
106 dig_line_box(CPoints, &box);
107 cline = dig_add_line(plus, GV_CENTROID, CPoints, &box, fid);
108 G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
109 x, y, fid, cline);
110 dig_cidx_add_cat(plus, 1, (int)fid, cline, GV_CENTROID);
111
113 }
114 else {
115 G_warning(_("Unable to calculate centroid for area"));
116 }
117 }
118 V2__add_line_to_topo_sfa(Map, line, points, cats);
119 }
120
121 G_debug(3, "updated lines : %d , updated nodes : %d",
122 plus->uplist.n_uplines, plus->uplist.n_upnodes);
123
124 /* returns int line, but is defined as off_t for compatibility with
125 * Write_line_array in write.c */
126 return line;
127}
128
129/*!
130 \brief Rewrites feature at the given offset on level 2 (OGR/PostGIS
131 interface, pseudo-topological level)
132
133 Note: Topology must be built at level >= GV_BUILD_BASE
134
135 \param Map pointer to Map_info structure
136 \param line feature id to be rewritten
137 \param type feature type (see V1_write_line_ogr() for supported types)
138 \param points pointer to line_pnts structure (feature geometry)
139 \param cats pointer to line_cats structure feature categories
140
141 \return feature index in offset array (related to pseudo-topology)
142 \return -1 on error
143 */
145 const struct line_pnts *points,
146 const struct line_cats *cats)
147{
148 G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d", (int)line, type);
149
150 if (line < 1 || line > Map->plus.n_lines) {
151 G_warning(_("Attempt to access feature with invalid id (%d)"),
152 (int)line);
153 return -1;
154 }
155
156 if (type != V2_read_line_sfa(Map, NULL, NULL, line)) {
157 G_warning(_("Unable to rewrite feature (incompatible feature types)"));
158 return -1;
159 }
160
161 if (V2_delete_line_sfa(Map, line) != 0)
162 return -1;
163
164 return V2_write_line_sfa(Map, type, points, cats);
165}
166
167/*!
168 \brief Deletes feature on level 2 (OGR/PostGIS interface)
169
170 Note: Topology must be built at level >= GV_BUILD_BASE
171
172 \todo Update fidx
173
174 \param pointer to Map_info structure
175 \param line feature id to be deleted
176
177 \return 0 on success
178 \return -1 on error
179 */
181{
182 int ret, i, type, first;
183 struct P_line *Line;
184 struct Plus_head *plus;
185 static struct line_cats *Cats = NULL;
186 static struct line_pnts *Points = NULL;
187
188 G_debug(3, "V2_delete_line_sfa(): line = %d", (int)line);
189
190 type = first = 0;
191 Line = NULL;
192 plus = &(Map->plus);
193
194 if (line < 1 || line > Map->plus.n_lines) {
195 G_warning(_("Attempt to access feature with invalid id (%d)"),
196 (int)line);
197 return -1;
198 }
199
200 if (!(plus->update_cidx)) {
201 plus->cidx_up_to_date = FALSE; /* category index will be outdated */
202 }
203
204 if (plus->built >= GV_BUILD_BASE) {
205 Line = Map->plus.Line[line];
206
207 if (Line == NULL)
208 G_fatal_error(_("Attempt to delete dead feature"));
209 type = Line->type;
210 }
211
212 if (!Cats) {
214 }
215 if (!Points) {
216 Points = Vect_new_line_struct();
217 }
218
219 type = V2_read_line_sfa(Map, Points, Cats, line);
220 if (type < 0)
221 return -1;
222
223 /* Update category index */
224 if (plus->update_cidx) {
225 for (i = 0; i < Cats->n_cats; i++) {
226 dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
227 }
228 }
229 /* Update fidx */
230 /* TODO */
231
232 /* delete the line from coor */
233 if (Map->format == GV_FORMAT_POSTGIS)
235 else
237
238 if (ret == -1) {
239 return ret;
240 }
241
242 /* Update topology */
243 if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
244 /* TODO */
245 /* remove centroid together with boundary (is really an OGR polygon) */
246 }
247 /* Delete reference from area */
248 if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
249 /* for OGR mapsets, virtual centroid will be removed when
250 * polygon is removed */
251 }
252
253 /* delete the line from topo */
254 dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
255
256 /* Rebuild areas/isles and attach centroids and isles */
257 if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
258 /* maybe not needed VERIFY */
259 }
260 return ret;
261}
262
263/*!
264 \brief Writes area on topological level (Simple Features interface,
265 internal use only)
266
267 \param Map pointer to Map_info structure
268 \param points feature geometry (exterior + interior rings)
269 \param nparts number of parts including exterior ring
270 \param cats feature categories
271
272 \return feature offset
273 \return -1 on error
274 */
275off_t V2__write_area_sfa(struct Map_info *Map, const struct line_pnts **points,
276 int nparts, const struct line_cats *cats)
277{
278 if (Map->format == GV_FORMAT_OGR) {
279 return V2__write_area_ogr(Map, points, nparts, cats);
280 }
281 else if (Map->format == GV_FORMAT_POSTGIS) {
282#ifdef HAVE_POSTGRES
283 return V2__write_area_pg(Map, points, nparts, cats);
284#else
285 G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
286 return -1;
287#endif
288 }
289 else {
290 G_warning(_("Unsupported vector map format (%d)"), Map->format);
291 }
292 return -1;
293}
294
295/*!
296 \brief Add feature to topo file (internal use only)
297
298 \param Map pointer to Map_info structure
299 \param line feature id
300 \param points pointer to line_pnts structure (feature geometry)
301 \param cats pointer to line_cats structure (feature categories)
302 */
303void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
304 const struct line_pnts *points,
305 const struct line_cats *cats)
306{
307 int first, s, i;
308 int type, area, side;
309
310 struct Plus_head *plus;
311 struct P_line *Line;
312
313 struct bound_box box, abox;
314
315 G_debug(3, "V2__add_line_to_topo_sfa(): line = %d npoints = %d", line,
316 points->n_points);
317
318 first = TRUE;
319 plus = &(Map->plus);
320 Line = plus->Line[line];
321 type = Line->type;
322
323 if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
324 struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
325
326 if (topo->N1 != topo->N2) {
327 G_warning(_("Boundary is not closed. Skipping."));
328 return;
329 }
330
331 /* Build new areas/isles */
332 for (s = 0; s < 2; s++) {
333 side = (s == 0 ? GV_LEFT : GV_RIGHT);
334 area = Vect_build_line_area(Map, line, side);
335 if (area > 0) { /* area */
336 Vect_get_area_box(Map, area, &box);
337 if (first) {
338 Vect_box_copy(&abox, &box);
339 first = FALSE;
340 }
341 else
342 Vect_box_extend(&abox, &box);
343 }
344 else if (area < 0) {
345 /* isle -> must be attached -> add to abox */
346 Vect_get_isle_box(Map, -area, &box);
347 if (first) {
348 Vect_box_copy(&abox, &box);
349 first = FALSE;
350 }
351 else
352 Vect_box_extend(&abox, &box);
353 }
354 G_debug(4, "Vect_build_line_area(): -> area = %d", area);
355 }
356
357 /* Attach centroid/isle to the new area */
358 if (plus->built >= GV_BUILD_ATTACH_ISLES)
360 if (plus->built >= GV_BUILD_CENTROIDS)
362 }
363
364 /* Add category index */
365 for (i = 0; i < cats->n_cats; i++) {
366 dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line, type);
367 }
368
369 return;
370}
#define NULL
Definition ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:75
int Vect_attach_centroids(struct Map_info *, const struct bound_box *)
(Re)Attach centroids in given bounding box to areas
Definition build.c:496
int V1_delete_line_pg(struct Map_info *, off_t)
Deletes feature at the given offset (level 1)
Definition write_pg.c:323
int Vect_build_line_area(struct Map_info *, int, int)
Build area on given side of line (GV_LEFT or GV_RIGHT)
Definition build.c:70
off_t V1_write_line_ogr(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes feature on level 1 (OGR interface)
Definition write_ogr.c:60
int Vect_box_extend(struct bound_box *, const struct bound_box *)
Extend box A by box B.
int Vect_get_point_in_poly(const struct line_pnts *, double *, double *)
Get point inside polygon.
Definition Vlib/poly.c:236
int Vect_get_area_box(struct Map_info *, int, struct bound_box *)
Get bounding box of area.
int V1_delete_line_ogr(struct Map_info *, off_t)
Deletes feature at the given offset on level 1 (OGR interface)
Definition write_ogr.c:106
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_get_isle_box(struct Map_info *, int, struct bound_box *)
Get bounding box of isle.
int Vect_attach_isles(struct Map_info *, const struct bound_box *)
(Re)Attach isles in given bounding box to areas
Definition build.c:418
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:146
int V2_read_line_sfa(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Reads feature from OGR/PostGIS layer on topological level.
Definition read_sfa.c:38
int Vect_box_copy(struct bound_box *, const struct bound_box *)
Copy box B to box A.
off_t V1_write_line_pg(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes feature on level 1 (PostGIS interface)
Definition write_pg.c:108
#define GV_CENTROID
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition dig_defines.h:89
#define GV_BOUNDARY
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
#define GV_BUILD_AREAS
Topology levels - build areas.
#define GV_BUILD_CENTROIDS
Topology levels - assign centroids to areas.
#define GV_RIGHT
#define GV_FORMAT_OGR
OGR format.
Definition dig_defines.h:85
#define GV_LEFT
Boundary side indicator left/right.
int dig_cidx_add_cat(struct Plus_head *, int, int, int, int)
int dig_del_line(struct Plus_head *, int, double, double, double)
Delete line from Plus_head structure.
Definition plus_line.c:217
int dig_cidx_del_cat(struct Plus_head *, int, int, int, int)
int dig_cidx_add_cat_sorted(struct Plus_head *, int, int, int, int)
int dig_add_line(struct Plus_head *, int, const struct line_pnts *, const struct bound_box *, off_t)
Add new line to Plus_head structure.
Definition plus_line.c:133
int dig_line_box(const struct line_pnts *, struct bound_box *)
#define TRUE
Definition gis.h:75
#define FALSE
Definition gis.h:79
#define _(str)
Definition glocale.h:10
Data structure used for building pseudo-topology.
Vector map info.
Vector geometry.
char type
Line type.
off_t offset
Offset in coor file for line.
void * topo
Topology info.
Boundary topology.
Basic topology-related info.
struct P_line ** Line
Array of vector geometries.
int cidx_up_to_date
Category index to be updated.
int update_cidx
Update category index if vector is modified.
struct Plus_head::@10 uplist
List of updated lines/nodes.
struct bound_box box
Bounding box of features.
int built
Highest level of topology currently available.
Bounding box.
Definition dig_structs.h:62
Feature category info.
int * field
Array of layers (fields)
int * cat
Array of categories.
int n_cats
Number of categories attached to element.
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.
off_t V2__write_area_ogr(struct Map_info *Map, const struct line_pnts **points, int nparts, const struct line_cats *cats)
Writes area on topological level (OGR Simple Features interface, internal use only)
Definition write_ogr.c:145
off_t V2__write_area_pg(struct Map_info *Map, const struct line_pnts **points, int nparts, const struct line_cats *cats)
Writes area on topological level (PostGIS Simple Features interface, internal use only)
Definition write_pg.c:539
int V2_delete_line_sfa(struct Map_info *Map, off_t line)
Deletes feature on level 2 (OGR/PostGIS interface)
Definition write_sfa.c:180
off_t V2_rewrite_line_sfa(struct Map_info *Map, off_t line, int type, const struct line_pnts *points, const struct line_cats *cats)
Rewrites feature at the given offset on level 2 (OGR/PostGIS interface, pseudo-topological level)
Definition write_sfa.c:144
off_t V2__write_area_sfa(struct Map_info *Map, const struct line_pnts **points, int nparts, const struct line_cats *cats)
Writes area on topological level (Simple Features interface, internal use only)
Definition write_sfa.c:275
off_t V2_write_line_sfa(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats)
Writes feature on level 2 (OGR/PostGIS interface, pseudo-topological level)
Definition write_sfa.c:49
#define x