GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
build_sfa.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/build_sfa.c
3 
4  \brief Vector library - Building pseudo-topology for simple feature access
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  Line offset is
9  - centroids : FID
10  - other types : index of the first record (which is FID) in offset array.
11 
12  (C) 2001-2012 by the GRASS Development Team
13 
14  This program is free software under the GNU General Public License
15  (>=v2). Read the file COPYING that comes with GRASS for details.
16 
17  \author Radim Blazek
18  \author Piero Cavalieri
19  \author Various updates for GRASS 7 by Martin Landa <landa.martin gmail.com>
20 */
21 
22 #include <stdlib.h>
23 
24 #include <grass/gis.h>
25 #include <grass/vector.h>
26 #include <grass/glocale.h>
27 
28 /*!
29  \brief This structure keeps info about geometry parts above current
30  geometry, path to curent geometry in the feature. First 'part' number
31  however is feature id */
32 struct geom_parts
33 {
34  int *part;
35  int a_parts;
36  int n_parts;
37 };
38 
39 static void init_parts(struct geom_parts *);
40 static void reset_parts(struct geom_parts *);
41 static void free_parts(struct geom_parts *);
42 static void add_part(struct geom_parts *, int);
43 static void del_part(struct geom_parts *);
44 static void add_parts_to_offset(struct Format_info_offset *,
45  struct geom_parts *);
46 static int add_line(struct Plus_head *, struct Format_info_offset *,
47  int, struct line_pnts *,
48  int, struct geom_parts *);
49 
50 #ifdef HAVE_POSTGRES
51 #include "pg_local_proto.h"
52 
53 static int add_geometry_pg(struct Plus_head *,
54  struct Format_info_pg *,
55  struct feat_parts *, int,
56  int, int,
57  struct geom_parts *);
58 static void build_pg(struct Map_info *, int);
59 #endif
60 
61 #ifdef HAVE_OGR
62 #include <ogr_api.h>
63 
64 static int add_geometry_ogr(struct Plus_head *,
65  struct Format_info_ogr *,
66  OGRGeometryH, int, int,
67  struct geom_parts *);
68 
69 static void build_ogr(struct Map_info *, int);
70 #endif
71 
72 /*!
73  \brief Init parts
74 */
75 void init_parts(struct geom_parts * parts)
76 {
77  G_zero(parts, sizeof(struct geom_parts));
78 }
79 
80 /*!
81  \brief Reset parts
82 */
83 void reset_parts(struct geom_parts * parts)
84 {
85  parts->n_parts = 0;
86 }
87 
88 /*!
89  \brief Free parts
90 */
91 void free_parts(struct geom_parts * parts)
92 {
93  G_free(parts->part);
94  G_zero(parts, sizeof(struct geom_parts));
95 }
96 
97 /*!
98  \brief Add new part number to parts
99 */
100 void add_part(struct geom_parts *parts, int part)
101 {
102  if (parts->a_parts == parts->n_parts) {
103  parts->a_parts += 10;
104  parts->part = (int *) G_realloc((void *)parts->part,
105  parts->a_parts * sizeof(int));
106  }
107  parts->part[parts->n_parts] = part;
108  parts->n_parts++;
109 }
110 
111 /*!
112  \brief Remove last part
113 */
114 void del_part(struct geom_parts *parts)
115 {
116  parts->n_parts--;
117 }
118 
119 /*!
120  \brief Add parts to offset
121 */
122 void add_parts_to_offset(struct Format_info_offset *offset,
123  struct geom_parts *parts)
124 {
125  int i, j;
126 
127  if (offset->array_num + parts->n_parts >= offset->array_alloc) {
128  offset->array_alloc += parts->n_parts + 1000;
129  offset->array = (int *)G_realloc(offset->array,
130  offset->array_alloc * sizeof(int));
131  }
132  j = offset->array_num;
133  for (i = 0; i < parts->n_parts; i++) {
134  G_debug(4, "add offset %d", parts->part[i]);
135  offset->array[j] = parts->part[i];
136  j++;
137  }
138  offset->array_num += parts->n_parts;
139 }
140 
141 /*!
142  \brief Add line to support structures
143 */
144 int add_line(struct Plus_head *plus, struct Format_info_offset *offset,
145  int type, struct line_pnts *Points,
146  int FID, struct geom_parts *parts)
147 {
148  int line;
149  long offset_value;
150  struct bound_box box;
151 
152  if (type != GV_CENTROID) {
153  /* beginning in the offset array */
154  offset_value = offset->array_num;
155  }
156  else {
157  /* TODO : could be used to statore category ? */
158  /* because centroids are read from topology, not from layer */
159  offset_value = FID;
160  }
161 
162  G_debug(4, "Register line: FID = %d offset = %ld", FID, offset_value);
163  dig_line_box(Points, &box);
164  line = dig_add_line(plus, type, Points, &box, offset_value);
165  G_debug(4, "Line registered with line = %d", line);
166 
167  /* Set box */
168  if (line == 1)
169  Vect_box_copy(&(plus->box), &box);
170  else
171  Vect_box_extend(&(plus->box), &box);
172 
173  if (type != GV_BOUNDARY) {
174  dig_cidx_add_cat(plus, 1, (int)FID, line, type);
175  }
176  else {
177  dig_cidx_add_cat(plus, 0, 0, line, type);
178  }
179 
180  /* because centroids are read from topology, not from layer */
181  if (type != GV_CENTROID)
182  add_parts_to_offset(offset, parts);
183 
184  return line;
185 }
186 
187 #ifdef HAVE_POSTGRES
188 /*!
189  \brief Recursively add geometry (PostGIS) to topology
190 */
191 int add_geometry_pg(struct Plus_head *plus,
192  struct Format_info_pg *pg_info,
193  struct feat_parts *fparts, int ipart,
194  int FID, int build, struct geom_parts *parts)
195 {
196  int line, i, idx, area, isle, outer_area, ret;
197  int lines[1];
198  double area_size, x, y;
199  SF_FeatureType ftype;
200  struct bound_box box;
201  struct Format_info_offset *offset;
202  struct line_pnts *line_i;
203 
204  ftype = fparts->ftype[ipart];
205 
206  G_debug(4, "add_geometry_pg() FID = %d ftype = %d", FID, ftype);
207 
208  offset = &(pg_info->offset);
209 
210  outer_area = 0;
211 
212  switch(ftype) {
213  case SF_POINT:
214  G_debug(4, "Point");
215  line_i = pg_info->cache.lines[fparts->idx[ipart]];
216  add_line(plus, offset, GV_POINT, line_i,
217  FID, parts);
218  break;
219  case SF_LINESTRING:
220  G_debug(4, "LineString");
221  line_i = pg_info->cache.lines[fparts->idx[ipart]];
222  add_line(plus, offset, GV_LINE, line_i,
223  FID, parts);
224  break;
225  case SF_POLYGON:
226  G_debug(4, "Polygon");
227 
228  /* register boundaries */
229  idx = fparts->idx[ipart];
230  for (i = 0; i < fparts->nlines[ipart]; i++) {
231  line_i = pg_info->cache.lines[idx++];
232  G_debug(4, "part %d", i);
233  add_part(parts, i);
234  line = add_line(plus, offset, GV_BOUNDARY,
235  line_i, FID, parts);
236  del_part(parts);
237 
238  if (build < GV_BUILD_AREAS)
239  continue;
240 
241  /* add area (each inner ring is also area) */
242  dig_line_box(line_i, &box);
243  dig_find_area_poly(line_i, &area_size);
244 
245  if (area_size > 0) /* area clockwise */
246  lines[0] = line;
247  else
248  lines[0] = -line;
249 
250  area = dig_add_area(plus, 1, lines, &box);
251 
252  /* each area is also isle */
253  lines[0] = -lines[0]; /* island is counter clockwise */
254 
255  isle = dig_add_isle(plus, 1, lines, &box);
256 
257  if (build < GV_BUILD_ATTACH_ISLES)
258  continue;
259 
260  if (i == 0) { /* outer ring */
261  outer_area = area;
262  }
263  else { /* inner ring */
264  struct P_isle *Isle;
265 
266  Isle = plus->Isle[isle];
267  Isle->area = outer_area;
268 
269  dig_area_add_isle(plus, outer_area, isle);
270  }
271  }
272 
273  if (build >= GV_BUILD_CENTROIDS) {
274  /* create virtual centroid */
275  ret = Vect_get_point_in_poly_isl((const struct line_pnts *) pg_info->cache.lines[fparts->idx[ipart]],
276  (const struct line_pnts **) &pg_info->cache.lines[fparts->idx[ipart]] + 1,
277  fparts->nlines[ipart] - 1, &x, &y);
278  if (ret < -1) {
279  G_warning(_("Unable to calculate centroid for area %d"),
280  outer_area);
281  }
282  else {
283  struct P_area *Area;
284  struct P_topo_c *topo;
285  struct P_line *Line;
286  struct line_pnts *line_c;
287 
288  G_debug(4, " Centroid: %f, %f", x, y);
289  line_c = Vect_new_line_struct();
290  Vect_append_point(line_c, x, y, 0.0);
291  line = add_line(plus, offset, GV_CENTROID, line_c, FID, parts);
292 
293  Line = plus->Line[line];
294  topo = (struct P_topo_c *)Line->topo;
295  topo->area = outer_area;
296 
297  /* register centroid to area */
298  Area = plus->Area[outer_area];
299  Area->centroid = line;
300  Vect_destroy_line_struct(line_c);
301  }
302  }
303  break;
304  default:
305  G_warning(_("Feature type %d not supported"), ftype);
306  break;
307  }
308 
309  return 0;
310 }
311 
312 /*!
313  \brief Build pseudo-topology for PostGIS layers
314 */
315 void build_pg(struct Map_info *Map, int build)
316 {
317  int iFeature, ipart, fid, nrecords, npoints;
318  char *wkb_data;
319 
320  struct Format_info_pg *pg_info;
321 
322  struct feat_parts fparts;
323  struct geom_parts parts;
324 
325  pg_info = &(Map->fInfo.pg);
326 
327  /* initialize data structures */
328  init_parts(&parts);
329  G_zero(&fparts, sizeof(struct feat_parts));
330 
331  /* get all features */
332  if (Vect__open_cursor_next_line_pg(pg_info, TRUE, Map->plus.built) != 0)
333  return;
334 
335  /* scan records */
336  npoints = 0;
337  nrecords = PQntuples(pg_info->res);
338  G_debug(4, "build_pg(): nrecords = %d", nrecords);
339  G_message(_("Registering primitives..."));
340  for (iFeature = 0; iFeature < nrecords; iFeature++) {
341  /* get feature id */
342  fid = atoi(PQgetvalue(pg_info->res, iFeature, 1));
343  if (fid < 1)
344  continue; /* PostGIS Topology: skip features with negative
345  * fid (isles, universal face, ...) */
346 
347  wkb_data = PQgetvalue(pg_info->res, iFeature, 0);
348 
349  G_progress(iFeature + 1, 1e4);
350 
351  /* cache feature (lines) */
352  if (SF_NONE == Vect__cache_feature_pg(wkb_data, FALSE, FALSE,
353  &(pg_info->cache), &fparts)) {
354  G_warning(_("Feature %d without geometry skipped"),
355  iFeature + 1);
356  continue;
357  }
358 
359  /* register all parts */
360  reset_parts(&parts);
361  add_part(&parts, fid);
362  for (ipart = 0; ipart < fparts.n_parts; ipart++) {
363  if (fparts.nlines[ipart] < 1) {
364  G_warning(_("Feature %d without geometry skipped"), fid);
365  continue;
366  }
367 
368  npoints += pg_info->cache.lines[ipart]->n_points;
369 
370  G_debug(4, "Feature: fid = %d part = %d", fid, ipart);
371 
372  if (fparts.n_parts > 1)
373  add_part(&parts, ipart);
374  add_geometry_pg(&(Map->plus), pg_info, &fparts, ipart,
375  fid, build, &parts);
376  if (fparts.n_parts > 1)
377  del_part(&parts);
378  }
379 
380  /* read next feature from cache */
381  pg_info->cache.lines_next = 0;
382  }
383  G_progress(1, 1);
384 
385  G_message(n_("One primitive registered", "%d primitives registered", Map->plus.n_lines), Map->plus.n_lines);
386  G_message(n_("One vertex registered", "%d vertices registered", npoints), npoints);
387 
388  Map->plus.built = GV_BUILD_BASE;
389 
390  PQclear(pg_info->res);
391  pg_info->res = NULL;
392 
393  /* free allocated space */
394  free_parts(&parts);
395 }
396 #endif /* HAVE_POSTGRES */
397 
398 #ifdef HAVE_OGR
399 /*!
400  \brief Recursively add geometry (OGR) to topology
401 */
402 int add_geometry_ogr(struct Plus_head *plus,
403  struct Format_info_ogr *ogr_info,
404  OGRGeometryH hGeom, int FID, int build,
405  struct geom_parts *parts)
406 {
407  int i, ret, npoints, line;
408  int area, isle, outer_area;
409  int lines[1];
410  double area_size, x, y;
411  int eType, nRings, iPart, nParts, nPoints;
412 
413  struct bound_box box;
414  struct P_line *Line;
415  struct Format_info_offset *offset;
416 
417  OGRGeometryH hGeom2, hRing;
418 
419  G_debug(4, "add_geometry_ogr() FID = %d", FID);
420 
421  offset = &(ogr_info->offset);
422 
423  /* allocate space in cache */
424  if (!ogr_info->cache.lines) {
425  ogr_info->cache.lines_alloc = 1;
426  ogr_info->cache.lines = (struct line_pnts **) G_malloc(sizeof(struct line_pnts *));
427 
428  ogr_info->cache.lines_types = (int *) G_malloc(sizeof(int));
429  ogr_info->cache.lines[0] = Vect_new_line_struct();
430  ogr_info->cache.lines_types[0] = -1;
431  }
432 
433  npoints = outer_area = 0;
434  eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
435  G_debug(4, "OGR type = %d", eType);
436 
437  switch (eType) {
438  case wkbPoint:
439  G_debug(4, "Point");
440 
441  ogr_info->cache.lines_types[0] = GV_POINT;
442  Vect_reset_line(ogr_info->cache.lines[0]);
443  Vect_append_point(ogr_info->cache.lines[0], OGR_G_GetX(hGeom, 0),
444  OGR_G_GetY(hGeom, 0), OGR_G_GetZ(hGeom, 0));
445  add_line(plus, offset, GV_POINT, ogr_info->cache.lines[0], FID, parts);
446  npoints += ogr_info->cache.lines[0]->n_points;
447  break;
448 
449  case wkbLineString:
450  G_debug(4, "LineString");
451 
452  ogr_info->cache.lines_types[0] = GV_LINE;
453  nPoints = OGR_G_GetPointCount(hGeom);
454  Vect_reset_line(ogr_info->cache.lines[0]);
455  for (i = 0; i < nPoints; i++) {
456  Vect_append_point(ogr_info->cache.lines[0],
457  OGR_G_GetX(hGeom, i), OGR_G_GetY(hGeom, i),
458  OGR_G_GetZ(hGeom, i));
459  }
460  add_line(plus, offset, GV_LINE, ogr_info->cache.lines[0], FID, parts);
461  npoints += ogr_info->cache.lines[0]->n_points;
462  break;
463 
464  case wkbPolygon:
465  G_debug(4, "Polygon");
466 
467  nRings = OGR_G_GetGeometryCount(hGeom);
468  G_debug(4, "Number of rings: %d", nRings);
469 
470  /* alloc space for islands if needed */
471  if (nRings > ogr_info->cache.lines_alloc) {
472  ogr_info->cache.lines_alloc += nRings;
473  ogr_info->cache.lines = (struct line_pnts **) G_realloc(ogr_info->cache.lines,
474  ogr_info->cache.lines_alloc *
475  sizeof(struct line_pnts *));
476  ogr_info->cache.lines_types = (int *) G_realloc(ogr_info->cache.lines_types,
477  ogr_info->cache.lines_alloc * sizeof(int));
478 
479  for (i = ogr_info->cache.lines_alloc - nRings; i < ogr_info->cache.lines_alloc; i++) {
480  ogr_info->cache.lines[i] = Vect_new_line_struct();
481  ogr_info->cache.lines_types[i] = -1;
482  }
483  }
484 
485  /* go through rings */
486  for (iPart = 0; iPart < nRings; iPart++) {
487  ogr_info->cache.lines_types[iPart] = GV_BOUNDARY;
488  hRing = OGR_G_GetGeometryRef(hGeom, iPart);
489  nPoints = OGR_G_GetPointCount(hRing);
490  G_debug(4, " ring %d : nPoints = %d", iPart, nPoints);
491 
492  Vect_reset_line(ogr_info->cache.lines[iPart]);
493  for (i = 0; i < nPoints; i++) {
494  Vect_append_point(ogr_info->cache.lines[iPart],
495  OGR_G_GetX(hRing, i), OGR_G_GetY(hRing, i),
496  OGR_G_GetZ(hRing, i));
497  }
498  npoints += ogr_info->cache.lines[iPart]->n_points;
499 
500  /* register boundary */
501  add_part(parts, iPart);
502  line = add_line(plus, offset, GV_BOUNDARY, ogr_info->cache.lines[iPart], FID, parts);
503  del_part(parts);
504 
505  if (build < GV_BUILD_AREAS)
506  continue;
507 
508  /* add area (each inner ring is also area) */
509  dig_line_box(ogr_info->cache.lines[iPart], &box);
510  dig_find_area_poly(ogr_info->cache.lines[iPart], &area_size);
511 
512  if (area_size > 0) /* area clockwise */
513  lines[0] = line;
514  else
515  lines[0] = -line;
516 
517  area = dig_add_area(plus, 1, lines, &box);
518 
519  /* each area is also isle */
520  lines[0] = -lines[0]; /* island is counter clockwise */
521 
522  isle = dig_add_isle(plus, 1, lines, &box);
523 
524  if (build < GV_BUILD_ATTACH_ISLES)
525  continue;
526 
527  if (iPart == 0) { /* outer ring */
528  outer_area = area;
529  }
530  else { /* inner ring */
531  struct P_isle *Isle;
532 
533  Isle = plus->Isle[isle];
534  Isle->area = outer_area;
535 
536  dig_area_add_isle(plus, outer_area, isle);
537  }
538  }
539 
540  if (build >= GV_BUILD_CENTROIDS) {
541  /* create virtual centroid */
542  ret = Vect_get_point_in_poly_isl((const struct line_pnts *) ogr_info->cache.lines[0],
543  (const struct line_pnts **) ogr_info->cache.lines + 1,
544  nRings - 1, &x, &y);
545  if (ret < -1) {
546  G_warning(_("Unable to calculate centroid for area %d"),
547  outer_area);
548  }
549  else {
550  struct P_area *Area;
551  struct P_topo_c *topo;
552 
553  G_debug(4, " Centroid: %f, %f", x, y);
554  Vect_reset_line(ogr_info->cache.lines[0]);
555  Vect_append_point(ogr_info->cache.lines[0], x, y, 0.0);
556  line = add_line(plus, offset, GV_CENTROID, ogr_info->cache.lines[0],
557  FID, parts);
558 
559  Line = plus->Line[line];
560  topo = (struct P_topo_c *)Line->topo;
561  topo->area = outer_area;
562 
563  /* register centroid to area */
564  Area = plus->Area[outer_area];
565  Area->centroid = line;
566  }
567  }
568  break;
569 
570  case wkbMultiPoint:
571  case wkbMultiLineString:
572  case wkbMultiPolygon:
573  case wkbGeometryCollection:
574  nParts = OGR_G_GetGeometryCount(hGeom);
575  G_debug(4, "%d geoms -> next level", nParts);
576 
577  /* alloc space for parts if needed */
578  if (nParts > ogr_info->cache.lines_alloc) {
579  ogr_info->cache.lines_alloc += nParts;
580  ogr_info->cache.lines = (struct line_pnts **) G_realloc(ogr_info->cache.lines,
581  ogr_info->cache.lines_alloc *
582  sizeof(struct line_pnts *));
583  ogr_info->cache.lines_types = (int *) G_realloc(ogr_info->cache.lines_types,
584  ogr_info->cache.lines_alloc * sizeof(int));
585 
586  for (i = ogr_info->cache.lines_alloc - nParts; i < ogr_info->cache.lines_alloc; i++) {
587  ogr_info->cache.lines[i] = Vect_new_line_struct();
588  ogr_info->cache.lines_types[i] = -1;
589  }
590  }
591 
592  /* go through all parts */
593  for (i = 0; i < nParts; i++) {
594  add_part(parts, i);
595  hGeom2 = OGR_G_GetGeometryRef(hGeom, i);
596  npoints += add_geometry_ogr(plus, ogr_info, hGeom2,
597  FID, build, parts);
598  del_part(parts);
599  }
600  break;
601 
602  default:
603  G_warning(_("OGR feature type %d not supported"), eType);
604  break;
605  }
606 
607  return npoints;
608 }
609 
610 void build_ogr(struct Map_info *Map, int build)
611 {
612  int iFeature, FID, npoints, nskipped;
613 
614  struct Format_info_ogr *ogr_info;
615 
616  OGRFeatureH hFeature;
617  OGRGeometryH hGeom;
618 
619  struct geom_parts parts;
620 
621  ogr_info = &(Map->fInfo.ogr);
622 
623  /* initialize data structures */
624  init_parts(&parts);
625 
626  /* Note: Do not use OGR_L_GetFeatureCount (it may scan all features) */
627  OGR_L_ResetReading(ogr_info->layer);
628  if (ogr_info->where)
629  /* set attribute filter if where sql statement defined */
630  OGR_L_SetAttributeFilter(ogr_info->layer, ogr_info->where);
631  npoints = iFeature = nskipped = 0;
632  G_message(_("Registering primitives..."));
633  while ((hFeature = OGR_L_GetNextFeature(ogr_info->layer)) != NULL) {
634  G_debug(3, " Feature %d", iFeature);
635 
636  G_progress(++iFeature, 1e4);
637 
638  hGeom = OGR_F_GetGeometryRef(hFeature);
639  if (hGeom == NULL) {
640  G_debug(3, "Feature %d without geometry skipped", iFeature);
641  OGR_F_Destroy(hFeature);
642  nskipped++;
643  continue;
644  }
645 
646  FID = (int) OGR_F_GetFID(hFeature);
647  if (FID == OGRNullFID) {
648  G_debug(3, "OGR feature %d without ID skipped", iFeature);
649  OGR_F_Destroy(hFeature);
650  nskipped++;
651  continue;
652  }
653  G_debug(4, " FID = %d", FID);
654 
655  reset_parts(&parts);
656  add_part(&parts, FID);
657  npoints += add_geometry_ogr(&(Map->plus), ogr_info, hGeom,
658  FID, build, &parts);
659 
660  OGR_F_Destroy(hFeature);
661  } /* while */
662  G_progress(1, 1);
663 
664  G_message(n_("One primitive registered", "%d primitives registered", Map->plus.n_lines), Map->plus.n_lines);
665  G_message(n_("One vertex registered", "%d vertices registered", npoints), npoints);
666 
667  if (nskipped > 0)
668  G_warning(n_("One feature without geometry skipped", "%d features without geometry skipped", nskipped), nskipped);
669 
670  Map->plus.built = GV_BUILD_BASE;
671 
672  free_parts(&parts);
673 }
674 #endif /* HAVE_OGR */
675 
676 /*!
677  \brief Build pseudo-topology (for simple features) - internal use only
678 
679  See Vect_build_ogr() and Vect_build_pg() for implementation issues.
680 
681  Build levels:
682  - GV_BUILD_NONE
683  - GV_BUILD_BASE
684  - GV_BUILD_ATTACH_ISLES
685  - GV_BUILD_CENTROIDS
686  - GV_BUILD_ALL
687 
688  \param Map pointer to Map_info structure
689  \param build build level
690 
691  \return 1 on success
692  \return 0 on error
693 */
694 int Vect__build_sfa(struct Map_info *Map, int build)
695 {
696  struct Plus_head *plus;
697 
698  plus = &(Map->plus);
699 
700  /* check if upgrade or downgrade */
701  if (build < plus->built) {
702  /* -> downgrade */
703  Vect__build_downgrade(Map, build);
704  return 1;
705  }
706 
707  /* -> upgrade */
708  if (plus->built < GV_BUILD_BASE) {
709  if (Map->format == GV_FORMAT_OGR ||
710  Map->format == GV_FORMAT_OGR_DIRECT) {
711 #ifdef HAVE_OGR
712  build_ogr(Map, build);
713 #else
714  G_fatal_error(_("GRASS is not compiled with OGR support"));
715 #endif
716  }
717  else if (Map->format == GV_FORMAT_POSTGIS) {
718 #ifdef HAVE_POSTGRES
719  build_pg(Map, build);
720 #else
721  G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
722 #endif
723  }
724  else {
725  G_fatal_error(_("%s: Native format unsupported"),
726  "Vect__build_sfa()");
727  }
728  }
729 
730  plus->built = build;
731 
732  return 1;
733 }
734 
735 /*!
736  \brief Dump feature index to file
737 
738  \param Map pointer to Map_info struct
739  \param out file for output (stdout/stderr for example)
740 
741  \return 1 on success
742  \return 0 on error
743  */
744 int Vect_fidx_dump(const struct Map_info *Map, FILE *out)
745 {
746  int i;
747  const struct Format_info_offset *offset;
748 
749  if (Map->format != GV_FORMAT_OGR &&
750  Map->format != GV_FORMAT_POSTGIS) {
751  G_warning(_("Feature index is built only for non-native formats. "
752  "Nothing to dump."));
753  return 0;
754  }
755 
756  if (Map->format == GV_FORMAT_OGR)
757  offset = &(Map->fInfo.ogr.offset);
758  else
759  offset = &(Map->fInfo.pg.offset);
760 
761  fprintf(out, "---------- FEATURE INDEX DUMP ----------\n");
762 
763  fprintf(out, "format: %s\n", Vect_maptype_info(Map));
764  if (Vect_maptype(Map) == GV_FORMAT_POSTGIS &&
765  Map->fInfo.pg.toposchema_name)
766  fprintf(out, "topology: PostGIS\n");
767  else
768  fprintf(out, "topology: pseudo\n");
769  fprintf(out, "feature type: %s\n",
771  fprintf(out, "number of features: %d\n\noffset : value (fid or part idx):\n",
772  Vect_get_num_lines(Map));
773  for (i = 0; i < offset->array_num; i++) {
774  fprintf(out, "%6d : %d\n", i, offset->array[i]);
775  }
776 
777  return 1;
778 }
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:699
int * array
Offset list.
Definition: dig_structs.h:446
#define TRUE
Definition: gis.h:59
#define G_malloc(n)
Definition: defs/gis.h:112
Bounding box.
Definition: dig_structs.h:65
const char * Vect_maptype_info(const struct Map_info *)
Gets vector map format (as string)
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int built
Highest level of topology currently available.
Definition: dig_structs.h:873
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1537
int Vect__build_sfa(struct Map_info *Map, int build)
Build pseudo-topology (for simple features) - internal use only.
Definition: build_sfa.c:694
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int Vect_box_copy(struct bound_box *, const struct bound_box *)
Copy box B to box A.
plus_t Vect_get_num_lines(const struct Map_info *)
Fetch number of features (points, lines, boundaries, centroids) in vector map.
Definition: level_two.c:74
Isle (topology) info.
Definition: dig_structs.h:1646
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:573
struct Format_info_offset offset
Offset list used for building pseudo-topology.
Definition: dig_structs.h:589
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
Definition: dig_defines.h:125
#define n_(strs, strp, num)
Definition: glocale.h:11
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:891
int dig_line_box(const struct line_pnts *, struct bound_box *)
int n_points
Number of points.
Definition: dig_structs.h:1692
int dig_area_add_isle(struct Plus_head *, int, int)
Add isle to area if does not exist yet.
Definition: plus_area.c:258
#define GV_CENTROID
Definition: dig_defines.h:185
#define GV_FORMAT_OGR
OGR format.
Definition: dig_defines.h:85
int dig_add_isle(struct Plus_head *, int, plus_t *, struct bound_box *)
Allocate space for new island and create boundary info from array.
Definition: plus_area.c:682
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1415
void G_progress(long, int)
Print progress info messages.
Definition: percent.c:160
struct P_isle ** Isle
Array of isles.
Definition: dig_structs.h:895
int Vect_get_point_in_poly_isl(const struct line_pnts *, const struct line_pnts **, int, double *, double *)
Get point inside polygon but outside the islands specifiled in IPoints.
Definition: Vlib/poly.c:457
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1628
#define NULL
Definition: ccmath.h:32
#define x
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:182
int Vect__open_cursor_next_line_pg(struct Format_info_pg *pg_info, int fetch_all, int built_level)
Create select cursor for sequential access (internal use only)
Definition: read_pg.c:1234
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
#define GV_LINE
Definition: dig_defines.h:183
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
void G_message(const char *,...) __attribute__((format(printf
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
Centroid topology.
Definition: dig_structs.h:1532
Basic topology-related info.
Definition: dig_structs.h:784
int Vect_fidx_dump(const struct Map_info *Map, FILE *out)
Dump feature index to file.
Definition: build_sfa.c:744
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
Non-native format info (PostGIS)
Definition: dig_structs.h:602
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:683
#define FALSE
Definition: gis.h:63
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
int Vect_maptype(const struct Map_info *)
Gets vector map format.
void * topo
Topology info.
Definition: dig_structs.h:1599
int lines_alloc
Number of allocated lines in cache.
Definition: dig_structs.h:485
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:726
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition: line.c:149
#define GV_BOUNDARY
Definition: dig_defines.h:184
#define GV_FORMAT_OGR_DIRECT
OGR format (direct access)
Definition: dig_defines.h:87
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
Non-native format info (OGR)
Definition: dig_structs.h:516
int Vect_box_extend(struct bound_box *, const struct bound_box *)
Extend box A by box B.
struct Format_info_ogr ogr
OGR info.
Definition: dig_structs.h:722
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:877
int dig_add_area(struct Plus_head *, int, plus_t *, struct bound_box *)
Allocate space for new area and create boundary info from array.
Definition: plus_area.c:184
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
Definition: dig_defines.h:129
int array_num
Number of items in offset list.
Definition: dig_structs.h:450
int * lines_types
List of line types (GV_POINT, GV_LINE, ...)
Definition: dig_structs.h:477
int array_alloc
Space allocated for offset list.
Definition: dig_structs.h:454
Vector map info.
Definition: dig_structs.h:1259
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
Area (topology) info.
Definition: dig_structs.h:1605
struct Format_info_offset offset
Offset list used for building pseudo-topology (simple features access)
Definition: dig_structs.h:689
SF_FeatureType Vect__cache_feature_pg(const char *data, int skip_polygon, int force_type, struct Format_info_cache *cache, struct feat_parts *fparts)
Read geometry from HEX data.
Definition: read_pg.c:757
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition: gis/zero.c:23
void G_warning(const char *,...) __attribute__((format(printf
const char * Vect_get_finfo_geometry_type(const struct Map_info *)
Get geometry type as string (relevant only for non-native formats)
Definition: header_finfo.c:144
struct line_pnts ** lines
Lines array.
Definition: dig_structs.h:473
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
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
void add_part(SYMBOL *s, SYMBPART *p)
Definition: symbol/read.c:71
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
plus_t area
Area it exists w/in, if any.
Definition: dig_structs.h:1669
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition: line.c:130
SF_FeatureType
Simple feature types.
Definition: dig_defines.h:234
int dig_find_area_poly(struct line_pnts *, double *)
Definition: diglib/poly.c:100
void Vect__build_downgrade(struct Map_info *, int)
Downgrade build level (for internal use only)
Definition: build.c:760