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