GRASS GIS 7 Programmer's Manual  7.5.svn(2017)-r71933
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 2)
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  See write_ogr.c (OGR interface) and write_pg.c (PostGIS interface)
9  for imlementation issues.
10 
11  \todo SFA version of V2__delete_area_cats_from_cidx_nat()
12  \todo function to delete corresponding entry in fidx
13  \todo SFA version of V2__add_area_cats_to_cidx_nat
14  \todo SFA version of V2__add_line_to_topo_nat
15 
16  (C) 2011-2012 by Martin Landa, and the GRASS Development Team
17 
18  This program is free software under the GNU General Public License
19  (>=v2). Read the file COPYING that comes with GRASS for details.
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 
33 #if defined HAVE_OGR || defined HAVE_POSTGRES
34 static void V2__add_line_to_topo_sfa(struct Map_info *, int, const struct line_pnts *,
35  const struct line_cats *);
36 #endif
37 
38 /*!
39  \brief Writes feature on level 2 (OGR/PostGIS interface, pseudo-topological level)
40 
41  \param Map pointer to Map_info structure
42  \param type feature type (see V1_write_line_ogr() for list of supported types)
43  \param points pointer to line_pnts structure (feature geometry)
44  \param 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 */
49 off_t V2_write_line_sfa(struct Map_info *Map, int type,
50  const struct line_pnts *points, const struct line_cats *cats)
51 {
52 #if defined HAVE_OGR || defined HAVE_POSTGRES
53  int line;
54  off_t offset;
55  struct Plus_head *plus;
56  struct bound_box box;
57  struct Format_info_offset *offset_info;
58 
59  line = 0;
60  plus = &(Map->plus);
61 
62  G_debug(3, "V2_write_line_sfa(): type = %d (format = %d)",
63  type, 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) {
101  CPoints = Vect_new_line_struct();
102  Vect_append_point(CPoints, x, y, 0.0);
103 
104  fid = offset_info->array[offset];
105 
106  dig_line_box(CPoints, &box);
107  cline = dig_add_line(plus, GV_CENTROID,
108  CPoints, &box, fid);
109  G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
110  x, y, fid, cline);
111  dig_cidx_add_cat(plus, 1, (int) fid,
112  cline, GV_CENTROID);
113 
114  Vect_destroy_line_struct(CPoints);
115  }
116  else {
117  G_warning(_("Unable to calculate centroid for area"));
118  }
119  }
120  V2__add_line_to_topo_sfa(Map, line, points, cats);
121  }
122 
123 
124  G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
125  plus->uplist.n_upnodes);
126 
127  /* returns int line, but is defined as off_t for compatibility with
128  * Write_line_array in write.c */
129  return line;
130 #else
131  G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
132  return -1;
133 #endif
134 }
135 
136 /*!
137  \brief Rewrites feature at the given offset on level 2 (OGR/PostGIS
138  interface, pseudo-topological level)
139 
140  Note: Topology must be built at level >= GV_BUILD_BASE
141 
142  \param Map pointer to Map_info structure
143  \param line feature id to be rewritten
144  \param type feature type (see V1_write_line_ogr() for supported types)
145  \param points pointer to line_pnts structure (feature geometry)
146  \param cats pointer to line_cats structure feature categories
147 
148  \return feature index in offset array (related to pseudo-topology)
149  \return -1 on error
150 */
151 off_t V2_rewrite_line_sfa(struct Map_info *Map, off_t line, int type,
152  const struct line_pnts *points, const struct line_cats *cats)
153 {
154  G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d",
155  (int)line, type);
156 
157  if (line < 1 || line > Map->plus.n_lines) {
158  G_warning(_("Attempt to access feature with invalid id (%d)"), (int)line);
159  return -1;
160  }
161 
162 #if defined HAVE_OGR || defined HAVE_POSTGRES
163  if (type != V2_read_line_sfa(Map, NULL, NULL, line)) {
164  G_warning(_("Unable to rewrite feature (incompatible feature types)"));
165  return -1;
166  }
167 
168  if (V2_delete_line_sfa(Map, line) != 0)
169  return -1;
170 
171  return V2_write_line_sfa(Map, type, points, cats);
172 #else
173  G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
174  return -1;
175 #endif
176 }
177 
178 /*!
179  \brief Deletes feature on level 2 (OGR/PostGIS interface)
180 
181  Note: Topology must be built at level >= GV_BUILD_BASE
182 
183  \todo Update fidx
184 
185  \param pointer to Map_info structure
186  \param line feature id to be deleted
187 
188  \return 0 on success
189  \return -1 on error
190 */
191 int V2_delete_line_sfa(struct Map_info *Map, off_t line)
192 {
193 #if defined HAVE_OGR || defined HAVE_POSTGRES
194  int ret, i, type, first;
195  struct P_line *Line;
196  struct Plus_head *plus;
197  static struct line_cats *Cats = NULL;
198  static struct line_pnts *Points = NULL;
199 
200  G_debug(3, "V2_delete_line_sfa(): line = %d", (int)line);
201 
202  type = first = 0;
203  Line = NULL;
204  plus = &(Map->plus);
205 
206  if (line < 1 || line > Map->plus.n_lines) {
207  G_warning(_("Attempt to access feature with invalid id (%d)"), (int)line);
208  return -1;
209  }
210 
211  if (!(plus->update_cidx)) {
212  plus->cidx_up_to_date = FALSE; /* category index will be outdated */
213  }
214 
215  if (plus->built >= GV_BUILD_BASE) {
216  Line = Map->plus.Line[line];
217 
218  if (Line == NULL)
219  G_fatal_error(_("Attempt to delete dead feature"));
220  type = Line->type;
221  }
222 
223  if (!Cats) {
224  Cats = Vect_new_cats_struct();
225  }
226  if (!Points) {
227  Points = Vect_new_line_struct();
228  }
229 
230  type = V2_read_line_sfa(Map, Points, Cats, line);
231  if (type < 0)
232  return -1;
233 
234  /* Update category index */
235  if (plus->update_cidx) {
236  for (i = 0; i < Cats->n_cats; i++) {
237  dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
238  }
239  }
240  /* Update fidx */
241  /* TODO */
242 
243  /* delete the line from coor */
244  if (Map->format == GV_FORMAT_POSTGIS)
245  ret = V1_delete_line_pg(Map, Line->offset);
246  else
247  ret = V1_delete_line_ogr(Map, Line->offset);
248 
249  if (ret == -1) {
250  return ret;
251  }
252 
253  /* Update topology */
254  if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
255  /* TODO */
256  /* remove centroid together with boundary (is really an OGR polygon) */
257  }
258  /* Delete reference from area */
259  if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
260  /* for OGR mapsets, virtual centroid will be removed when
261  * polygon is removed */
262  }
263 
264  /* delete the line from topo */
265  dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
266 
267  /* Rebuild areas/isles and attach centroids and isles */
268  if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
269  /* maybe not needed VERIFY */
270  }
271  return ret;
272 #else
273  G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
274  return -1;
275 #endif
276 }
277 
278 /*!
279  \brief Writes area on topological level (Simple Features interface,
280  internal use only)
281 
282  \param Map pointer to Map_info structure
283  \param points feature geometry (exterior + interior rings)
284  \param nparts number of parts including exterior ring
285  \param cats feature categories
286 
287  \return feature offset
288  \return -1 on error
289 */
290 off_t V2__write_area_sfa(struct Map_info *Map,
291  const struct line_pnts **points, int nparts,
292  const struct line_cats *cats)
293 {
294  if (Map->format == GV_FORMAT_OGR) {
295 #ifdef HAVE_OGR
296  return V2__write_area_ogr(Map, points, nparts, cats);
297 #else
298  G_fatal_error(_("GRASS is not compiled with OGR support"));
299  return -1;
300 #endif
301  }
302  else if (Map->format == GV_FORMAT_POSTGIS) {
303 #ifdef HAVE_POSTGRES
304  return V2__write_area_pg(Map, points, nparts, cats);
305 #else
306  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
307  return -1;
308 #endif
309  }
310  else {
311  G_warning(_("Unsupported vector map format (%d)"), Map->format);
312  }
313  return -1;
314 }
315 
316 #if defined HAVE_OGR || defined HAVE_POSTGRES
317 /*!
318  \brief Add feature to topo file (internal use only)
319 
320  \param Map pointer to Map_info structure
321  \param line feature id
322  \param points pointer to line_pnts structure (feature geometry)
323  \param cats pointer to line_cats structure (feature categories)
324 */
325 void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
326  const struct line_pnts *points,
327  const struct line_cats *cats)
328 {
329  int first, s, i;
330  int type, area, side;
331 
332  struct Plus_head *plus;
333  struct P_line *Line;
334 
335  struct bound_box box, abox;
336 
337  G_debug(3, "V2__add_line_to_topo_sfa(): line = %d npoints = %d", line,
338  points->n_points);
339 
340  plus = &(Map->plus);
341  Line = plus->Line[line];
342  type = Line->type;
343 
344  if (plus->built >= GV_BUILD_AREAS &&
345  type == GV_BOUNDARY) {
346  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
347 
348  if (topo->N1 != topo->N2) {
349  G_warning(_("Boundary is not closed. Skipping."));
350  return;
351  }
352 
353  /* Build new areas/isles */
354  for (s = 0; s < 2; s++) {
355  side = (s == 0 ? GV_LEFT : GV_RIGHT);
356  area = Vect_build_line_area(Map, line, side);
357  if (area > 0) { /* area */
358  Vect_get_area_box(Map, area, &box);
359  if (first) {
360  Vect_box_copy(&abox, &box);
361  first = FALSE;
362  }
363  else
364  Vect_box_extend(&abox, &box);
365  }
366  else if (area < 0) {
367  /* isle -> must be attached -> add to abox */
368  Vect_get_isle_box(Map, -area, &box);
369  if (first) {
370  Vect_box_copy(&abox, &box);
371  first = FALSE;
372  }
373  else
374  Vect_box_extend(&abox, &box);
375  }
376  G_debug(4, "Vect_build_line_area(): -> area = %d", area);
377  }
378 
379  /* Attach centroid/isle to the new area */
380  if (plus->built >= GV_BUILD_ATTACH_ISLES)
381  Vect_attach_isles(Map, &abox);
382  if (plus->built >= GV_BUILD_CENTROIDS)
383  Vect_attach_centroids(Map, &abox);
384  }
385 
386  /* Add category index */
387  for (i = 0; i < cats->n_cats; i++) {
388  dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
389  type);
390  }
391 
392  return;
393 }
394 #endif /* HAVE_OGR || HAVE_POSTGRES */
int * array
Offset list.
Definition: dig_structs.h:446
int Vect_get_isle_box(const struct Map_info *Map, int isle, struct bound_box *Box)
Get bounding box of isle.
Bounding box.
Definition: dig_structs.h:65
int built
Highest level of topology currently available.
Definition: dig_structs.h:873
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:163
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:174
int n_uplines
Number of updated lines.
Definition: dig_structs.h:1201
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1593
Vector geometry.
Definition: dig_structs.h:1574
if(!YY_CURRENT_BUFFER)
Definition: sqlp.yy.c:803
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int Vect_get_area_box(const struct Map_info *Map, int area, struct bound_box *Box)
Get bounding box of area.
struct line_pnts * Vect_new_line_struct()
Creates and initializes a line_pnts structure.
Definition: line.c:45
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
Definition: dig_defines.h:125
int dig_line_box(const struct line_pnts *, struct bound_box *)
int n_points
Number of points.
Definition: dig_structs.h:1692
#define GV_CENTROID
Definition: dig_defines.h:185
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
int V1_delete_line_ogr(struct Map_info *Map, off_t offset)
Deletes feature at the given offset on level 1 (OGR interface)
Definition: write_ogr.c:119
void Vect_destroy_line_struct(struct line_pnts *p)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition: line.c:77
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1415
#define NULL
Definition: ccmath.h:32
#define x
int Vect_attach_isles(struct Map_info *Map, const struct bound_box *box)
(Re)Attach isles in given bounding box to areas
Definition: build.c:416
plus_t N1
Start node.
Definition: dig_structs.h:1514
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:151
int Vect_attach_centroids(struct Map_info *Map, const struct bound_box *box)
(Re)Attach centroids in given bounding box to areas
Definition: build.c:494
int dig_del_line(struct Plus_head *, int, double, double, double)
Delete line from Plus_head structure.
Definition: plus_line.c:219
int V1_delete_line_pg(struct Map_info *Map, off_t offset)
Deletes feature at the given offset (level 1)
Definition: write_pg.c:310
int Vect_append_point(struct line_pnts *Points, double x, double y, double z)
Appends one point to the end of a line.
Definition: line.c:149
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:159
Feature category info.
Definition: dig_structs.h:1702
int dig_cidx_add_cat(struct Plus_head *, int, int, int, int)
Definition: diglib/cindex.c:73
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:136
double * x
Array of X coordinates.
Definition: dig_structs.h:1680
char type
Line type.
Definition: dig_structs.h:1586
int cidx_up_to_date
Category index to be updated.
Definition: dig_structs.h:1156
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
off_t V1_write_line_ogr(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats)
Writes feature on level 1 (OGR interface)
Definition: write_ogr.c:62
Basic topology-related info.
Definition: dig_structs.h:784
int dig_cidx_del_cat(struct Plus_head *, int, int, int, int)
Data structure used for building pseudo-topology.
Definition: dig_structs.h:397
#define GV_BUILD_AREAS
Topology levels - build areas.
Definition: dig_defines.h:127
int Vect_build_line_area(struct Map_info *Map, int iline, int side)
Build area on given side of line (GV_LEFT or GV_RIGHT)
Definition: build.c:77
#define FALSE
Definition: gis.h:53
void * topo
Topology info.
Definition: dig_structs.h:1599
int n_upnodes
number of updated nodes
Definition: dig_structs.h:1213
Boundary topology.
Definition: dig_structs.h:1509
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:726
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
int * cat
Array of categories.
Definition: dig_structs.h:1711
#define GV_BOUNDARY
Definition: dig_defines.h:184
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
off_t V1_write_line_pg(struct Map_info *Map, int type, const struct line_pnts *points, const struct line_cats *cats)
Writes feature on level 1 (PostGIS interface)
Definition: write_pg.c:98
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:877
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
int V2_read_line_sfa(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Reads feature from OGR/PostGIS layer on topological level.
Definition: read_sfa.c:40
int Vect_get_point_in_poly(const struct line_pnts *Points, double *X, double *Y)
Get point inside polygon.
Definition: Vlib/poly.c:211
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
Definition: dig_defines.h:129
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:290
Vector map info.
Definition: dig_structs.h:1259
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
int V2_delete_line_sfa(struct Map_info *Map, off_t line)
Deletes feature on level 2 (OGR/PostGIS interface)
Definition: write_sfa.c:191
double * y
Array of Y coordinates.
Definition: dig_structs.h:1684
struct Format_info_offset offset
Offset list used for building pseudo-topology (simple features access)
Definition: dig_structs.h:689
struct line_cats * Vect_new_cats_struct()
Creates and initializes line_cats structure.
int Vect_box_copy(struct bound_box *A, const struct bound_box *B)
Copy box B to box A.
#define GV_RIGHT
Definition: dig_defines.h:175
double * z
Array of Z coordinates.
Definition: dig_structs.h:1688
#define _(str)
Definition: glocale.h:13
int Vect_box_extend(struct bound_box *A, const struct bound_box *B)
Extend box A by box B.
int format
Map format (native, ogr, postgis)
Definition: dig_structs.h:1271
#define GV_BUILD_CENTROIDS
Topology levels - assign centroids to areas.
Definition: dig_defines.h:131
int * field
Array of layers (fields)
Definition: dig_structs.h:1707
struct Plus_head::@10 uplist
List of updated lines/nodes.
int dig_cidx_add_cat_sorted(struct Plus_head *, int, int, int, int)
plus_t N2
End node.
Definition: dig_structs.h:1518
int update_cidx
Update category index if vector is modified.
Definition: dig_structs.h:1136
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203