GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
build.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/build.c
3 
4  \brief Vector library - Building topology
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2001-2010, 2012-2013 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15  */
16 
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <unistd.h>
21 #include <math.h>
22 
23 #include <grass/vector.h>
24 #include <grass/glocale.h>
25 
26 #include "local_proto.h"
27 
28 #ifdef HAVE_POSTGRES
29 #include "pg_local_proto.h"
30 #endif
31 
32 #define SEP "-----------------------------------\n"
33 
34 #if !defined HAVE_OGR || !defined HAVE_POSTGRES
35 static int format()
36 {
37  G_fatal_error(_("Requested format is not compiled in this version"));
38  return 0;
39 }
40 #endif
41 
42 static int (*Build_array[]) () = {
44 #ifdef HAVE_OGR
46  , Vect_build_ogr
47 #else
48  , format
49  , format
50 #endif
51 #ifdef HAVE_POSTGRES
53 #else
54  , format
55 #endif
56 };
57 
58 /* for qsort */
59 
60 typedef struct {
61  int i;
62  double size;
63  struct bound_box box;
64 } BOX_SIZE;
65 
66 /*!
67  \brief Build area on given side of line (GV_LEFT or GV_RIGHT)
68 
69  \param Map pointer to Map_info structure
70  \param iline line id
71  \param side side (GV_LEFT or GV_RIGHT)
72 
73  \return > 0 area id
74  \return < 0 isle id
75  \return 0 not created (may also already exist)
76  */
77 int Vect_build_line_area(struct Map_info *Map, int iline, int side)
78 {
79  int area, isle, n_lines;
80 
81  struct Plus_head *plus;
82  struct bound_box box;
83  static struct line_pnts *APoints = NULL;
84  plus_t *lines;
85  double area_size;
86 
87  plus = &(Map->plus);
88 
89  G_debug(3, "Vect_build_line_area() line = %d, side = %d", iline, side);
90 
91  if (!APoints)
92  APoints = Vect_new_line_struct();
93 
94  /* get area */
95  area = dig_line_get_area(plus, iline, side);
96  if (area != 0) {
97  /* -> there is already an area on this side of the line, skip */
98  G_debug(3, " area/isle = %d -> skip", area);
99  return 0;
100  }
101 
102  /* build an area with this line */
103  n_lines = dig_build_area_with_line(plus, iline, side, &lines);
104  G_debug(3, " n_lines = %d", n_lines);
105  if (n_lines < 1) {
106  G_debug(3, " unable to build area with line %d", iline);
107  return 0;
108  } /* area was not built */
109 
110  /* get line points which forms a boundary of an area */
111  Vect__get_area_points(Map, lines, n_lines, APoints);
112  dig_line_box(APoints, &box);
113 
114  Vect_line_prune(APoints);
115  if (APoints->n_points < 4) {
116  G_warning(_("Area of size = 0.0 (less than 4 vertices) ignored"));
117  return 0;
118  }
119 
120  /* Area or island ? */
121  dig_find_area_poly(APoints, &area_size);
122 
123  /* area_size = dig_find_poly_orientation(APoints); */
124  /* area_size is not real area size, we are only interested in the sign */
125 
126  G_debug(3, " area/isle size = %f", area_size);
127 
128  if (area_size > 0) { /* CW: area */
129  /* add area structure to plus */
130  area = dig_add_area(plus, n_lines, lines, &box);
131  if (area == -1) { /* error */
132  G_fatal_error(_("Unable to add area (map closed, topo saved)"));
133  }
134  G_debug(3, " -> area %d", area);
135  return area;
136  }
137  else if (area_size < 0) { /* CCW: island */
138  isle = dig_add_isle(plus, n_lines, lines, &box);
139  if (isle == -1) { /* error */
140  G_fatal_error(_("Unable to add isle (map closed, topo saved)"));
141  }
142  G_debug(3, " -> isle %d", isle);
143  return -isle;
144  }
145  else {
146  /* TODO: What to do with such areas? Should be areas/isles of size 0 stored,
147  * so that may be found and cleaned by some utility
148  * Note: it would be useful for vertical closed polygons, but such would be added twice
149  * as area */
150  G_warning(_("Area of size = 0.0 ignored"));
151  }
152  return 0;
153 }
154 
155 /* qsort areas by size */
156 static int sort_by_size(const void *a, const void *b)
157 {
158  BOX_SIZE *as = (BOX_SIZE *)a;
159  BOX_SIZE *bs = (BOX_SIZE *)b;
160 
161  if (as->size < bs->size)
162  return -1;
163 
164  return (as->size > bs->size);
165 }
166 
167 /*!
168  \brief Find area outside island
169 
170  \param Map vector map
171  \param isle isle id
172  \param box isle bbox
173 
174  \return area id
175  \return 0 if not found
176  */
177 int Vect_isle_find_area(struct Map_info *Map, int isle, const struct bound_box *box)
178 {
179  int i, j, line, sel_area, area, poly;
180  const struct Plus_head *plus;
181  struct P_line *Line;
182  struct P_node *Node;
183  struct P_isle *Isle;
184  struct P_area *Area;
185  struct P_topo_b *topo;
186  struct bound_box *abox, nbox;
187  static struct boxlist *List = NULL;
188  static BOX_SIZE *size_list;
189  static int alloc_size_list = 0;
190 
191  /* see also Vect_find_area() */
192 
193  /* Note: We should check all isle points (at least) because if topology is not clean
194  * and two areas overlap, isle which is not completely within area may be attached,
195  * but it would take long time */
196 
197  G_debug(3, "Vect_isle_find_area () island = %d", isle);
198  plus = &(Map->plus);
199 
200  if (plus->Isle[isle] == NULL) {
201  G_warning(_("Request to find area outside nonexistent isle"));
202  return 0;
203  }
204 
205  if (!List) {
206  List = Vect_new_boxlist(1);
207  alloc_size_list = 10;
208  size_list = G_malloc(alloc_size_list * sizeof(BOX_SIZE));
209  }
210 
211  Isle = plus->Isle[isle];
212  line = abs(Isle->lines[0]);
213  Line = plus->Line[line];
214  topo = (struct P_topo_b *)Line->topo;
215  Node = plus->Node[topo->N1];
216 
217  /* select areas by box */
218  nbox.E = Node->x;
219  nbox.W = Node->x;
220  nbox.N = Node->y;
221  nbox.S = Node->y;
222  nbox.T = PORT_DOUBLE_MAX;
223  nbox.B = -PORT_DOUBLE_MAX;
224  Vect_select_areas_by_box(Map, &nbox, List);
225  G_debug(3, "%d areas overlap island boundary point", List->n_values);
226 
227  /* sort areas by bbox size
228  * get the smallest area that contains the isle
229  * using the bbox size is working because if 2 areas both contain
230  * the isle, one of these areas must be inside the other area
231  * which means that the bbox of the outer area must be larger than
232  * the bbox of the inner area, and equal bbox sizes are not possible */
233 
234  if (alloc_size_list < List->n_values) {
235  alloc_size_list = List->n_values;
236  size_list = G_realloc(size_list, alloc_size_list * sizeof(BOX_SIZE));
237  }
238 
239  j = 0;
240  for (i = 0; i < List->n_values; i++) {
241  abox = &List->box[i];
242 
243  if (box->E > abox->E || box->W < abox->W || box->N > abox->N ||
244  box->S < abox->S) {
245  G_debug(3, " isle not completely inside area box");
246  continue;
247  }
248 
249  List->id[j] = List->id[i];
250  List->box[j] = List->box[i];
251  size_list[j].i = List->id[j];
252  size_list[j].box = List->box[j];
253  size_list[j].size = (abox->N - abox->S) * (abox->E - abox->W);
254  j++;
255  }
256  List->n_values = j;
257 
258  if (List->n_values > 1) {
259  if (List->n_values == 2) {
260  /* simple swap */
261  if (size_list[1].size < size_list[0].size) {
262  size_list[0].i = List->id[1];
263  size_list[1].i = List->id[0];
264  size_list[0].box = List->box[1];
265  size_list[1].box = List->box[0];
266  }
267  }
268  else
269  qsort(size_list, List->n_values, sizeof(BOX_SIZE), sort_by_size);
270  }
271 
272  sel_area = 0;
273  for (i = 0; i < List->n_values; i++) {
274  area = size_list[i].i;
275  G_debug(3, "area = %d", area);
276 
277  Area = plus->Area[area];
278 
279  /* Before other tests, simply exclude those areas inside isolated isles formed by one boundary */
280  if (abs(Isle->lines[0]) == abs(Area->lines[0])) {
281  G_debug(3, " area inside isolated isle");
282  continue;
283  }
284 
285  /* Check box */
286  /* Note: If build is run on large files of areas imported from nontopo format (shapefile)
287  * attaching of isles takes very long time because each area is also isle and select by
288  * box all overlapping areas selects all areas with box overlapping first node.
289  * Then reading coordinates for all those areas would take a long time -> check first
290  * if isle's box is completely within area box */
291 
292  abox = &size_list[i].box;
293 
294  if (box->E > abox->E || box->W < abox->W || box->N > abox->N ||
295  box->S < abox->S) {
296  G_debug(3, " isle not completely inside area box");
297  continue;
298  }
299 
300  poly = Vect_point_in_area_outer_ring(Node->x, Node->y, Map, area, abox);
301  G_debug(3, " poly = %d", poly);
302 
303  if (poly == 1) { /* point in area, but node is not part of area inside isle (would be poly == 2) */
304 
305 #if 1
306  /* new version */
307  /* the bounding box of the smaller area is
308  * 1) inside the bounding box of a larger area and thus
309  * 2) smaller than the bounding box of a larger area */
310 
311  sel_area = area;
312  break;
313 #else
314  /* old version */
315 
316  /* In rare case island is inside more areas in that case we have to calculate area
317  * of outer ring and take the smaller */
318  if (sel_area == 0) { /* first */
319  sel_area = area;
320  }
321  else { /* is not first */
322  G_debug(1, "slow version of Vect_isle_find_area()");
323  if (cur_size < 0) { /* second area */
324  /* This is slow, but should not be called often */
325  Vect_get_area_points(Map, sel_area, APoints);
326  /* G_begin_polygon_area_calculations();
327  cur_size =
328  G_area_of_polygon(APoints->x, APoints->y,
329  APoints->n_points); */
330  /* this is faster, but there may be latlon problems: the poles */
331  dig_find_area_poly(APoints, &cur_size);
332  G_debug(3, " first area size = %f (n points = %d)",
333  cur_size, APoints->n_points);
334 
335  }
336 
337  Vect_get_area_points(Map, area, APoints);
338  /* size =
339  G_area_of_polygon(APoints->x, APoints->y,
340  APoints->n_points); */
341  /* this is faster, but there may be latlon problems: the poles */
342  dig_find_area_poly(APoints, &size);
343  G_debug(3, " area size = %f (n points = %d)", size,
344  APoints->n_points);
345 
346  if (size > 0 && size < cur_size) {
347  sel_area = area;
348  cur_size = size;
349  /* this can not happen because the first area must be
350  * inside the second area because the node
351  * is inside both areas */
352  G_warning(_("Larger bbox but smaller area!!!"));
353  }
354  }
355  G_debug(3, "sel_area = %d cur_size = %f", sel_area, cur_size);
356 #endif
357  }
358  }
359  if (sel_area > 0) {
360  G_debug(3, "Island %d in area %d", isle, sel_area);
361  }
362  else {
363  G_debug(3, "Island %d is not in area", isle);
364  }
365 
366  return sel_area;
367 }
368 
369 /*!
370  \brief (Re)Attach isle to area
371 
372  \param Map vector map
373  \param isle isle id
374  \param box isle bbox
375 
376  \return 0
377  */
378 int Vect_attach_isle(struct Map_info *Map, int isle, const struct bound_box *box)
379 {
380  int area;
381  struct P_isle *Isle;
382  struct Plus_head *plus;
383 
384  /* Note!: If topology is not clean and areas overlap, one island
385  may fall to more areas (partially or fully). Before isle is
386  attached to area it must be check if it is not attached yet */
387  G_debug(3, "Vect_attach_isle(): isle = %d", isle);
388 
389  plus = &(Map->plus);
390 
391  area = Vect_isle_find_area(Map, isle, box);
392  G_debug(3, "\tisle = %d -> area outside = %d", isle, area);
393  if (area > 0) {
394  Isle = plus->Isle[isle];
395  if (Isle->area > 0) {
396  G_debug(3, "Attempt to attach isle %d to more areas "
397  "(=>topology is not clean)", isle);
398  }
399  else {
400  Isle->area = area;
401  dig_area_add_isle(plus, area, isle);
402  }
403  }
404  return 0;
405 }
406 
407 /*!
408  \brief (Re)Attach isles in given bounding box to areas
409 
410  The warning for Vect_attach_centroids() applies here as well
411 
412  \param Map vector map
413  \param box bounding box
414 
415  \return 0
416  */
417 int Vect_attach_isles(struct Map_info *Map, const struct bound_box *box)
418 {
419  int i, isle, area;
420  struct bound_box abox;
421  static struct boxlist *List = NULL;
422  struct Plus_head *plus;
423 
424  G_debug(3, "Vect_attach_isles()");
425 
426  plus = &(Map->plus);
427 
428  if (!List)
429  List = Vect_new_boxlist(TRUE);
430 
431  Vect_select_isles_by_box(Map, box, List);
432  G_debug(3, " number of isles to attach = %d", List->n_values);
433 
434  for (i = 0; i < List->n_values; i++) {
435  isle = List->id[i];
436 
437  area = plus->Isle[isle]->area;
438 
439  if (area > 0) {
440  /* if the area box is not fully inside the box, detach
441  * this might detach more than needed,
442  * but all that need to be reattached and
443  * is faster than reattaching all */
444  Vect_get_area_box(Map, area, &abox);
445  if (box->W < abox.W && box->E > abox.E &&
446  box->S < abox.S && box->N > abox.N) {
447  G_debug(3, "Outer area is fully inside search box");
448  }
449  else {
450  dig_area_del_isle(plus, area, isle);
451  plus->Isle[isle]->area = 0;
452  area = 0;
453  }
454  }
455 
456  if (area == 0)
457  Vect_attach_isle(Map, isle, &List->box[i]);
458  }
459  return 0;
460 }
461 
462 /*!
463  \brief (Re)Attach centroids in given bounding box to areas
464 
465  Warning: If map is updated on level2, it may happen that
466  previously correct island becomes incorrect. In that case,
467  centroid of area forming the island is reattached to outer area,
468  because island polygon is not excluded.
469 
470  <pre>
471  +-----------+ +-----------+
472  | 1 | | 1 |
473  | +---+---+ | | +---+---+ |
474  | | 2 | 3 | | | | 2 | |
475  | | x | | | -> | | x | |
476  | | | | | | | | |
477  | +---+---+ | | +---+---+ |
478  | | | |
479  +-----------+ +-----------+
480  centroid is centroid is
481  attached to 2 reattached to 1
482  </pre>
483 
484  Because of this, when the centroid is reattached to another area,
485  it is always necessary to check if original area exist, unregister
486  centroid from previous area. To simplify code, this is
487  implemented so that centroid is always first unregistered and if
488  new area is found, it is registered again.
489 
490  \param Map vector map
491  \param box bounding box
492 
493  \return 0
494  */
495 int Vect_attach_centroids(struct Map_info *Map, const struct bound_box * box)
496 {
497  int i, area, centr;
498  static int first = 1;
499  struct bound_box abox;
500  static struct boxlist *List;
501  struct P_area *Area;
502  struct P_line *Line;
503  struct P_topo_c *topo;
504  struct Plus_head *plus;
505 
506  G_debug(3, "Vect_attach_centroids()");
507 
508  plus = &(Map->plus);
509 
510  if (first) {
511  List = Vect_new_boxlist(1);
512  first = 0;
513  }
514 
515  Vect_select_lines_by_box(Map, box, GV_CENTROID, List);
516  G_debug(3, "\tnumber of centroids to reattach = %d", List->n_values);
517  for (i = 0; i < List->n_values; i++) {
518 
519  centr = List->id[i];
520  Line = plus->Line[centr];
521  topo = (struct P_topo_c *)Line->topo;
522 
523  area = topo->area;
524 
525  if (area > 0) {
526  /* if the area box is not fully inside the box, detach
527  * this might detach more than needed,
528  * but all that need to be reattached and
529  * is faster than reattaching all */
530  Vect_get_area_box(Map, area, &abox);
531  if (box->W < abox.W && box->E > abox.E &&
532  box->S < abox.S && box->N > abox.N) {
533  G_debug(3, "Centroid's area is fully inside search box");
534  }
535  else {
536  Area = plus->Area[area];
537  Area->centroid = 0;
538  topo->area = 0;
539  area = 0;
540  }
541  }
542 
543  if (area > 0) {
544  continue;
545  }
546 
547  area = Vect_find_area(Map, List->box[i].E, List->box[i].N);
548  G_debug(3, "\tcentroid %d is in area %d", centr, area);
549  if (area > 0) {
550  Area = plus->Area[area];
551  if (Area->centroid == 0) { /* first centroid */
552  G_debug(3, "\tfirst centroid -> attach to area");
553  Area->centroid = centr;
554  topo->area = area;
555  }
556  else if (Area->centroid != centr) { /* duplicate centroid */
557  /* Note: it cannot happen that Area->centroid == centr, because the centroid
558  * was not registered or a duplicate */
559  G_debug(3, "\tduplicate centroid -> do not attach to area");
560  topo->area = -area;
561  }
562  }
563  }
564 
565  return 0;
566 }
567 
568 /*!
569  \brief Build topology for vector map
570 
571  \param Map vector map
572 
573  \return 1 on success
574  \return 0 on error
575  */
576 int Vect_build(struct Map_info *Map)
577 {
578  return Vect_build_partial(Map, GV_BUILD_ALL);
579 }
580 
581 /*!
582  \brief Extensive tests for correct topology
583 
584  - lines or boundaries of zero length
585  - intersecting boundaries, ie. overlapping areas
586  - areas without centroids that are not isles
587 
588  \param Map vector map
589  \param[out] Err vector map where errors will be written or NULL
590 
591  \return 1 on success
592  \return 0 on error
593  */
594 int Vect_topo_check(struct Map_info *Map, struct Map_info *Err)
595 {
596  int line, nlines;
597  int nerrors, n_zero_lines, n_zero_boundaries;
598  struct line_pnts *Points;
599  struct line_cats *Cats;
600 
601  /* rebuild topology if needed */
602  if (Vect_get_built(Map) != GV_BUILD_ALL) {
604  Vect_build(Map);
605  }
606 
607  G_message(_("Checking for topological errors..."));
608 
609  Points = Vect_new_line_struct();
610  Cats = Vect_new_cats_struct();
611 
612  /* lines or boundaries of zero length */
613  n_zero_lines = n_zero_boundaries = 0;
614  nlines = Vect_get_num_lines(Map);
615  for (line = 1; line <= nlines; line++) {
616  int type;
617 
618  if (!Vect_line_alive(Map, line))
619  continue;
620 
621  type = Vect_get_line_type(Map, line);
622 
623  if (type & GV_LINES) {
624  double len;
625 
626  Vect_read_line(Map, Points, Cats, line);
627  len = Vect_line_length(Points);
628 
629  if (len == 0) {
630  if (type & GV_LINE)
631  n_zero_lines++;
632  else if (type & GV_BOUNDARY)
633  n_zero_boundaries++;
634 
635  if (Err)
636  Vect_write_line(Err, type, Points, Cats);
637  }
638  }
639  }
640 
641  if (n_zero_lines)
642  G_warning(_("Number of lines of length zero: %d"), n_zero_lines);
643  if (n_zero_boundaries)
644  G_warning(_("Number of boundaries of length zero: %d"), n_zero_boundaries);
645 
646  /* remaining checks are for areas only */
647  if (Vect_get_num_primitives(Map, GV_BOUNDARY) == 0)
648  return 1;
649 
650  /* intersecting boundaries -> overlapping areas */
651  nerrors = Vect_check_line_breaks(Map, GV_BOUNDARY, Err);
652  if (nerrors)
653  G_warning(_("Number of boundary intersections: %d"), nerrors);
654 
655  /* areas without centroids that are not isles
656  * only makes sense if all boundaries are correct */
657  nerrors = 0;
658  for (line = 1; line <= nlines; line++) {
659  int type;
660 
661  if (!Vect_line_alive(Map, line))
662  continue;
663 
664  type = Vect_get_line_type(Map, line);
665 
666  if (type == GV_BOUNDARY) {
667  struct P_topo_b *topo = (struct P_topo_b *)Map->plus.Line[line]->topo;
668 
669  if (topo->left == 0 || topo->right == 0) {
670  G_debug(3, "line = %d left = %d right = %d", line,
671  topo->left, topo->right);
672  nerrors++;
673  }
674  }
675  }
676  if (nerrors)
677  G_warning(_("Skipping further checks because of incorrect boundaries"));
678  else {
679  int i, area, left, right, neighbour;
680  int nareas = Vect_get_num_areas(Map);
681  struct ilist *List = Vect_new_list();
682 
683  nerrors = 0;
684  for (area = 1; area <= nareas; area++) {
685  if (!Vect_area_alive(Map, area))
686  continue;
687  line = Vect_get_area_centroid(Map, area);
688  if (line != 0)
689  continue; /* has centroid */
690 
691  Vect_get_area_boundaries(Map, area, List);
692  for (i = 0; i < List->n_values; i++) {
693  line = List->value[i];
694  Vect_get_line_areas(Map, abs(line), &left, &right);
695  if (line > 0)
696  neighbour = left;
697  else
698  neighbour = right;
699 
700  if (neighbour < 0) {
701  neighbour = Vect_get_isle_area(Map, abs(neighbour));
702  if (!neighbour) {
703  /* borders outer void */
704  nerrors++;
705  if (Err) {
706  Vect_read_line(Map, Points, Cats, abs(line));
707  Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
708  }
709  }
710  /* else neighbour is > 0, check below */
711  }
712  if (neighbour > 0) {
713  if (Vect_get_area_centroid(Map, neighbour) == 0) {
714  /* neighbouring area does not have a centroid either */
715  nerrors++;
716  if (Err) {
717  Vect_read_line(Map, Points, Cats, abs(line));
718  Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
719  }
720  }
721  }
722  }
723  }
724  Vect_destroy_list(List);
725 
726  if (nerrors)
727  G_warning(_("Number of redundant holes: %d"),
728  nerrors);
729  }
730 
731  /* what else ? */
732 
733  Vect_destroy_line_struct(Points);
735 
736  return 1;
737 }
738 
739 /*!
740  \brief Return current highest built level (part)
741 
742  \param Map vector map
743 
744  \return current highest built level
745  */
746 int Vect_get_built(const struct Map_info *Map)
747 {
748  return Map->plus.built;
749 }
750 
751 /*!
752  \brief Downgrade build level (for internal use only)
753 
754  See Vect_build_nat(), Vect__build_sfa(), and Vect_build_pg() for
755  implementation issues.
756 
757  \param Map pointer to Map_info
758  \param build
759 */
760 void Vect__build_downgrade(struct Map_info *Map, int build)
761 {
762  int line;
763  struct Plus_head *plus;
764  struct P_line *Line;
765 
766  plus = &(Map->plus);
767 
768  /* lower level request - release old sources (this also
769  initializes structures and numbers of elements) */
770  if (plus->built >= GV_BUILD_CENTROIDS && build < GV_BUILD_CENTROIDS) {
771  /* reset info about areas stored for centroids */
772  for (line = 1; line <= plus->n_lines; line++) {
773  Line = plus->Line[line];
774  if (Line && Line->type == GV_CENTROID) {
775  struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
776  topo->area = 0;
777  }
778  }
779  dig_free_plus_areas(plus);
780  dig_spidx_free_areas(plus);
781  dig_free_plus_isles(plus);
782  dig_spidx_free_isles(plus);
783  }
784 
785  if (plus->built >= GV_BUILD_AREAS && build < GV_BUILD_AREAS) {
786  /* reset info about areas stored for lines */
787  for (line = 1; line <= plus->n_lines; line++) {
788  Line = plus->Line[line];
789  if (Line && Line->type == GV_BOUNDARY) {
790  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
791  topo->left = 0;
792  topo->right = 0;
793  }
794  }
795  dig_free_plus_areas(plus);
796  dig_spidx_free_areas(plus);
797  dig_free_plus_isles(plus);
798  dig_spidx_free_isles(plus);
799  }
800 
801  if (plus->built >= GV_BUILD_BASE && build < GV_BUILD_BASE) {
802  dig_free_plus_nodes(plus);
803  dig_spidx_free_nodes(plus);
804  dig_free_plus_lines(plus);
805  dig_spidx_free_lines(plus);
806  }
807 
808  plus->built = build;
809 }
810 
811 /*!
812  \brief Build partial topology for vector map.
813 
814  Should only be used in special cases of vector processing.
815 
816  This functions optionally builds only some parts of
817  topology. Highest level is specified by build parameter which may
818  be:
819  - GV_BUILD_NONE - nothing is build
820  - GV_BUILD_BASE - basic topology, nodes, lines, spatial index;
821  - GV_BUILD_AREAS - build areas and islands, but islands are not attached to areas;
822  - GV_BUILD_ATTACH_ISLES - attach islands to areas;
823  - GV_BUILD_CENTROIDS - assign centroids to areas, build category index;
824  - GV_BUILD_ALL - top level, the same as GV_BUILD_CENTROIDS.
825 
826  If functions is called with build lower than current value of the
827  Map, the level is downgraded to requested value.
828 
829  All calls to Vect_write_line(), Vect_rewrite_line(),
830  Vect_delete_line() respect the last value of build used in this
831  function.
832 
833  Note that the functions has effect only if requested level is
834  higher than current level, to rebuild part of topology, call first
835  downgrade and then upgrade, for example:
836 
837  - Vect_build()
838  - Vect_build_partial(,GV_BUILD_BASE,)
839  - Vect_build_partial(,GV_BUILD_AREAS,)
840 
841  \param Map vector map
842  \param build highest level of build
843 
844  \return 1 on success
845  \return 0 on error
846  */
847 int Vect_build_partial(struct Map_info *Map, int build)
848 {
849  struct Plus_head *plus;
850  int ret;
851 
852  G_debug(3, "Vect_build(): build = %d", build);
853 
854  /* If topology is already build (map on > level 2), set level to 1
855  * so that lines will be read by V1_read_ (all lines) */
856  Map->level = LEVEL_1; /* may be not needed, because V1_read is used
857  directly by Vect_build_ */
858 
859  if (Map->format != GV_FORMAT_OGR_DIRECT &&
860  !(Map->format == GV_FORMAT_POSTGIS && Map->fInfo.pg.toposchema_name))
861  /* don't write support files for OGR direct and PostGIS Topology */
862  Map->support_updated = TRUE;
863 
864  if (!Map->plus.Spidx_built) {
865  if (Vect_open_sidx(Map, 2) < 0)
866  G_fatal_error(_("Unable to open spatial index file for vector map <%s>"),
867  Vect_get_full_name(Map));
868  }
869 
870  plus = &(Map->plus);
871  if (build > GV_BUILD_NONE && !Map->temporary && Map->format != GV_FORMAT_POSTGIS) {
872  G_message(_("Building topology for vector map <%s>..."),
873  Vect_get_full_name(Map));
874  }
875  plus->with_z = Map->head.with_z;
876  plus->spidx_with_z = Map->head.with_z;
877 
878  if (build == GV_BUILD_ALL && plus->built < GV_BUILD_ALL) {
879  dig_cidx_free(plus); /* free old (if any) category index */
880  dig_cidx_init(plus);
881  }
882 
883  ret = ((*Build_array[Map->format]) (Map, build));
884  if (ret == 0) {
885  return 0;
886  }
887 
888  if (build > GV_BUILD_NONE) {
889  Map->level = LEVEL_2;
890  G_verbose_message(_("Topology was built"));
891  }
892 
893  plus->mode = GV_MODE_WRITE;
894 
895  if (build == GV_BUILD_ALL) {
896  plus->cidx_up_to_date = TRUE; /* category index was build */
897  dig_cidx_sort(plus);
898  }
899 
900  if (build > GV_BUILD_NONE) {
901  G_verbose_message(_("Number of nodes: %d"), plus->n_nodes);
902  G_verbose_message(_("Number of primitives: %d"), plus->n_lines);
903  G_verbose_message(_("Number of points: %d"), plus->n_plines);
904  G_verbose_message(_("Number of lines: %d"), plus->n_llines);
905  G_verbose_message(_("Number of boundaries: %d"), plus->n_blines);
906  G_verbose_message(_("Number of centroids: %d"), plus->n_clines);
907 
908  if (plus->n_flines > 0)
909  G_verbose_message(_("Number of faces: %d"), plus->n_flines);
910 
911  if (plus->n_klines > 0)
912  G_verbose_message(_("Number of kernels: %d"), plus->n_klines);
913  }
914 
915  if (plus->built >= GV_BUILD_AREAS) {
916  int line, nlines, area, nareas, err_boundaries, err_centr_out,
917  err_centr_dupl, err_nocentr;
918  struct P_line *Line;
919  struct Plus_head *Plus;
920 
921  /* Count errors (it does not take much time comparing to build process) */
922  Plus = &(Map->plus);
923  nlines = Vect_get_num_lines(Map);
924  err_boundaries = err_centr_out = err_centr_dupl = 0;
925  for (line = 1; line <= nlines; line++) {
926  Line = Plus->Line[line];
927  if (!Line)
928  continue;
929  if (Line->type == GV_BOUNDARY) {
930  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
931 
932  if (topo->left == 0 || topo->right == 0) {
933  G_debug(3, "line = %d left = %d right = %d", line,
934  topo->left, topo->right);
935  err_boundaries++;
936  }
937  }
938  if (Line->type == GV_CENTROID) {
939  struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
940 
941  if (topo->area == 0)
942  err_centr_out++;
943  else if (topo->area < 0)
944  err_centr_dupl++;
945  }
946  }
947 
948  err_nocentr = 0;
949  nareas = Vect_get_num_areas(Map);
950  for (area = 1; area <= nareas; area++) {
951  if (!Vect_area_alive(Map, area))
952  continue;
953  line = Vect_get_area_centroid(Map, area);
954  if (line == 0)
955  err_nocentr++;
956  }
957 
958  G_verbose_message(_("Number of areas: %d"), plus->n_areas);
959  G_verbose_message(_("Number of isles: %d"), plus->n_isles);
960 
961 #if 0
962  /* not an error, message disabled to avoid confusion */
963  if (err_nocentr)
964  G_message(_("Number of areas without centroid: %d"),
965  err_nocentr);
966 #endif
967 
968  if (plus->n_clines > plus->n_areas)
969  G_warning(_("Number of centroids exceeds number of areas: %d > %d"),
970  plus->n_clines, plus->n_areas);
971 
972  if (err_boundaries)
973  G_warning(_("Number of incorrect boundaries: %d"),
974  err_boundaries);
975 
976  if (err_centr_out)
977  G_warning(_("Number of centroids outside area: %d"),
978  err_centr_out);
979 
980  if (err_centr_dupl)
981  G_warning(_("Number of duplicate centroids: %d"), err_centr_dupl);
982 
983  }
984  else if (build > GV_BUILD_NONE) {
985  G_verbose_message(_("Number of areas: -"));
986  G_verbose_message(_("Number of isles: -"));
987  }
988  return 1;
989 }
990 
991 /*!
992  \brief Save topology file for vector map
993 
994  \param Map pointer to Map_info structure
995 
996  \return 1 on success
997  \return 0 on error
998  */
999 int Vect_save_topo(struct Map_info *Map)
1000 {
1001  struct Plus_head *plus;
1002  char path[GPATH_MAX];
1003  struct gvfile fp;
1004 
1005  G_debug(1, "Vect_save_topo()");
1006 
1007  /* write out all the accumulated info to the plus file */
1008  plus = &(Map->plus);
1009  dig_file_init(&fp);
1010 
1011  Vect__get_path(path, Map);
1012  fp.file = G_fopen_new(path, GV_TOPO_ELEMENT);
1013  if (fp.file == NULL) {
1014  G_warning(_("Unable to create topo file for vector map <%s>"), Map->name);
1015  return 0;
1016  }
1017 
1018  /* set portable info */
1020 
1021  if (0 > dig_write_plus_file(&fp, plus)) {
1022  G_warning(_("Error writing out topo file"));
1023  return 0;
1024  }
1025 
1026  fclose(fp.file);
1027 
1028  return 1;
1029 }
1030 
1031 /*!
1032  \brief Dump topology to file
1033 
1034  \param Map vector map
1035  \param out file for output (stdout/stderr for example)
1036 
1037  \return 1 on success
1038  \return 0 on error
1039  */
1040 int Vect_topo_dump(const struct Map_info *Map, FILE *out)
1041 {
1042  int i, j, line, isle;
1043  float angle_deg;
1044  struct P_node *Node;
1045  struct P_line *Line;
1046  struct P_area *Area;
1047  struct P_isle *Isle;
1048  struct bound_box box;
1049  const struct Plus_head *plus;
1050 
1051  plus = &(Map->plus);
1052 
1053  fprintf(out, "---------- TOPOLOGY DUMP ----------\n");
1054  fprintf(out, "Map: %s\n", Vect_get_full_name(Map));
1055  fprintf(out, "Topology format: ");
1056  if (Map->format == GV_FORMAT_NATIVE)
1057  fprintf(out, "native");
1058  else if (Map->format == GV_FORMAT_POSTGIS &&
1059  Map->fInfo.pg.toposchema_name) {
1060  fprintf(out, "PostGIS");
1061  }
1062  else {
1063  fprintf(out, "pseudo (simple features)");
1064  if (Map->format == GV_FORMAT_OGR)
1065  fprintf(out, " @ OGR");
1066  else
1067  fprintf(out, " @ PostgreSQL");
1068  }
1069  fprintf(out, "\n");
1070 
1071  fprintf(out, SEP);
1072 
1073  /* box */
1074  Vect_box_copy(&box, &(plus->box));
1075  fprintf(out, "N,S,E,W,T,B: %f, %f, %f, %f, %f, %f\n", box.N, box.S,
1076  box.E, box.W, box.T, box.B);
1077 
1078  fprintf(out, SEP);
1079 
1080  /* nodes */
1081  fprintf(out, "Nodes (%d nodes, alive + dead):\n", plus->n_nodes);
1082  for (i = 1; i <= plus->n_nodes; i++) {
1083  if (plus->Node[i] == NULL) {
1084  continue;
1085  }
1086  Node = plus->Node[i];
1087  fprintf(out, "node = %d, n_lines = %d, xyz = %f, %f, %f\n", i,
1088  Node->n_lines, Node->x, Node->y, Node->z);
1089  for (j = 0; j < Node->n_lines; j++) {
1090  line = Node->lines[j];
1091  Line = plus->Line[abs(line)];
1092  angle_deg = (Node->angles[j] * 180) / M_PI;
1093  if (angle_deg < 0)
1094  angle_deg += 360;
1095  fprintf(out, " line = %3d, type = %d, angle = %f (%.4f)\n", line,
1096  Line->type, Node->angles[j], angle_deg);
1097  }
1098  }
1099 
1100  fprintf(out, SEP);
1101 
1102  /* lines */
1103  fprintf(out, "Lines (%d lines, alive + dead):\n", plus->n_lines);
1104  for (i = 1; i <= plus->n_lines; i++) {
1105  if (plus->Line[i] == NULL) {
1106  continue;
1107  }
1108  Line = plus->Line[i];
1109  if (Line->type == GV_POINT) {
1110  fprintf(out, "line = %d, type = %d, offset = %lu\n",
1111  i, Line->type, (unsigned long)Line->offset);
1112  }
1113  else if (Line->type == GV_CENTROID) {
1114  struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
1115 
1116  fprintf(out, "line = %d, type = %d, offset = %lu, area = %d\n",
1117  i, Line->type, (unsigned long)Line->offset, topo->area);
1118  }
1119  else if (Line->type == GV_LINE) {
1120  struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
1121 
1122  fprintf(out, "line = %d, type = %d, offset = %lu, n1 = %d, n2 = %d\n",
1123  i, Line->type, (unsigned long)Line->offset, topo->N1,
1124  topo->N2);
1125  }
1126  else if (Line->type == GV_BOUNDARY) {
1127  struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
1128 
1129  fprintf(out, "line = %d, type = %d, offset = %lu, n1 = %d, n2 = %d, "
1130  "left = %d, right = %d\n",
1131  i, Line->type, (unsigned long)Line->offset, topo->N1,
1132  topo->N2, topo->left, topo->right);
1133  }
1134  else if (Line->type == GV_FACE) {
1135  struct P_topo_f *topo = (struct P_topo_f *)Line->topo;
1136 
1137  fprintf(out, "line = %d, type = %d, offset = %lu, e1 = %d, e2 = %d, "
1138  "e3 = %d, left = %d, right = %d\n",
1139  i, Line->type, (unsigned long)Line->offset, topo->E[0],
1140  topo->E[1], topo->E[2], topo->left, topo->right);
1141  }
1142  else if (Line->type == GV_KERNEL) {
1143  struct P_topo_k *topo = (struct P_topo_k *)Line->topo;
1144 
1145  fprintf(out, "line = %d, type = %d, offset = %lu, volume = %d",
1146  i, Line->type, (unsigned long)Line->offset, topo->volume);
1147  }
1148  }
1149 
1150  fprintf(out, SEP);
1151 
1152  /* areas */
1153  fprintf(out, "Areas (%d areas, alive + dead):\n", plus->n_areas);
1154  for (i = 1; i <= plus->n_areas; i++) {
1155  if (plus->Area[i] == NULL) {
1156  continue;
1157  }
1158  Area = plus->Area[i];
1159 
1160  fprintf(out, "area = %d, n_lines = %d, n_isles = %d centroid = %d\n",
1161  i, Area->n_lines, Area->n_isles, Area->centroid);
1162 
1163  for (j = 0; j < Area->n_lines; j++) {
1164  line = Area->lines[j];
1165  Line = plus->Line[abs(line)];
1166  fprintf(out, " line = %3d\n", line);
1167  }
1168  for (j = 0; j < Area->n_isles; j++) {
1169  isle = Area->isles[j];
1170  fprintf(out, " isle = %3d\n", isle);
1171  }
1172  }
1173 
1174  fprintf(out, SEP);
1175 
1176  /* isles */
1177  fprintf(out, "Islands (%d islands, alive + dead):\n", plus->n_isles);
1178  for (i = 1; i <= plus->n_isles; i++) {
1179  if (plus->Isle[i] == NULL) {
1180  continue;
1181  }
1182  Isle = plus->Isle[i];
1183 
1184  fprintf(out, "isle = %d, n_lines = %d area = %d\n", i, Isle->n_lines,
1185  Isle->area);
1186 
1187  for (j = 0; j < Isle->n_lines; j++) {
1188  line = Isle->lines[j];
1189  Line = plus->Line[abs(line)];
1190  fprintf(out, " line = %3d\n", line);
1191  }
1192  }
1193 
1194  return 1;
1195 }
1196 
1197 /*!
1198  \brief Create spatial index if necessary.
1199 
1200  To be used in modules.
1201  Map must be opened on level 2.
1202 
1203  \param[in,out] Map pointer to vector map
1204 
1205  \return 0 OK
1206  \return 1 error
1207  */
1208 int Vect_build_sidx(struct Map_info *Map)
1209 {
1210  if (Map->level < 2) {
1211  G_fatal_error(_("Unable to build spatial index from topology, "
1212  "vector map is not opened at topology level 2"));
1213  }
1214  if (!Map->plus.Spidx_built) {
1215  return Vect_build_sidx_from_topo(Map);
1216  }
1217  return 0;
1218 }
1219 
1220 /*!
1221  \brief Create spatial index from topology if necessary (not longer
1222  supported)
1223 
1224  \param Map pointer to vector map
1225 
1226  \return 1
1227  */
1228 int Vect_build_sidx_from_topo(const struct Map_info *Map)
1229 {
1230 
1231  G_debug(3, "Vect_build_sidx_from_topo(): name=%s",
1232  Vect_get_full_name(Map));
1233 
1234  G_warning(_("%s is no longer supported"), "Vect_build_sidx_from_topo()");
1235 
1236  return 1;
1237 }
1238 
1239 /*!
1240  \brief Save spatial index file for vector map
1241 
1242  \param Map vector map
1243 
1244  \return 1 on success
1245  \return 0 on error
1246  */
1247 int Vect_save_sidx(struct Map_info *Map)
1248 {
1249  struct Plus_head *plus;
1250  char file_path[GPATH_MAX];
1251 
1252  G_debug(1, "Vect_save_spatial_index()");
1253 
1254  plus = &(Map->plus);
1255 
1256  if (!plus->Spidx_built) {
1257  G_warning(_("Spatial index not available, can not be saved"));
1258  return 0;
1259  }
1260 
1261  /* new or update mode ? */
1262  if (plus->Spidx_new == TRUE) {
1263  /* write out rtrees to sidx file */
1264  Vect__get_element_path(file_path, Map, GV_SIDX_ELEMENT);
1265  G_debug(1, "Open sidx: %s", file_path);
1266  dig_file_init(&(plus->spidx_fp));
1267  plus->spidx_fp.file = fopen(file_path, "w+");
1268  if (plus->spidx_fp.file == NULL) {
1269  G_warning(_("Unable to create spatial index file for vector map <%s>"),
1270  Vect_get_name(Map));
1271  return 0;
1272  }
1273 
1274  /* set portable info */
1276 
1277  if (0 > dig_Wr_spidx(&(plus->spidx_fp), plus)) {
1278  G_warning(_("Error writing out spatial index file"));
1279  return 0;
1280  }
1281  Map->plus.Spidx_new = FALSE;
1282  }
1283 
1284  fclose(Map->plus.spidx_fp.file);
1285 
1286  Map->plus.Spidx_built = FALSE;
1287 
1288  return 1;
1289 }
1290 
1291 /*!
1292  \brief Dump spatial index to file
1293 
1294  \param Map vector map
1295  \param out file for output (stdout/stderr for example)
1296 
1297  \return 1 on success
1298  \return 0 on error
1299  */
1300 int Vect_sidx_dump(const struct Map_info *Map, FILE * out)
1301 {
1302  if (!(Map->plus.Spidx_built)) {
1304  }
1305 
1306  fprintf(out, "---------- SPATIAL INDEX DUMP ----------\n");
1307 
1308  dig_dump_spidx(out, &(Map->plus));
1309 
1310  return 1;
1311 }
int Vect_get_area_box(const struct Map_info *, int, struct bound_box *)
Get bounding box of area.
int Vect_build_pg(struct Map_info *, int)
Build topology for PostGIS layer.
Definition: build_pg.c:57
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:699
int Spidx_new
Build new spatial index.
Definition: dig_structs.h:1059
#define TRUE
Definition: gis.h:59
#define G_malloc(n)
Definition: defs/gis.h:112
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:951
plus_t right
Volume number to the right, negative for hole.
Definition: dig_structs.h:1557
char * name
Map name (for 4.0)
Definition: dig_structs.h:1332
Bounding box.
Definition: dig_structs.h:65
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void dig_spidx_free_areas(struct Plus_head *)
Reset spatial index for areas.
Definition: spindex.c:171
int plus_t
plus_t size
Definition: dig_structs.h:41
if(!(yy_init))
Definition: sqlp.yy.c:775
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 * id
Array of ids.
Definition: dig_structs.h:1755
int Vect_select_areas_by_box(struct Map_info *, const struct bound_box *, struct boxlist *)
Select areas with bounding boxes by box.
Definition: sindex.c:125
char * Vect__get_element_path(char *file_path, const struct Map_info *Map, const char *element)
Get map element full path (internal use only)
void dig_init_portable(struct Port_info *, int)
Set Port_info structure to byte order of file.
Definition: portable.c:905
plus_t n_klines
Current number of kernels.
Definition: dig_structs.h:922
int Vect_get_built(const struct Map_info *Map)
Return current highest built level (part)
Definition: build.c:746
double W
West.
Definition: dig_structs.h:82
int dig_dump_spidx(FILE *, const struct Plus_head *)
Dump spatial index.
Definition: spindex_rw.c:1273
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1593
int Vect_build_nat(struct Map_info *, int)
Build topology.
Definition: build_nat.c:34
int Vect_select_isles_by_box(struct Map_info *, const struct bound_box *, struct boxlist *)
Select isles with bounding boxes by box.
Definition: sindex.c:171
#define GV_FORMAT_NATIVE
Geometry data formats supported by lib Don&#39;t change GV_FORMAT_* values, this order is hardcoded in li...
Definition: dig_defines.h:83
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int spidx_with_z
2D/3D spatial index
Definition: dig_structs.h:809
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
int Vect_get_area_centroid(const struct Map_info *, int)
Returns centroid id for given area.
int with_z
2D/3D vector data
Definition: dig_structs.h:802
Isle (topology) info.
Definition: dig_structs.h:1646
plus_t n_plines
Current number of points.
Definition: dig_structs.h:902
int Vect_point_in_area_outer_ring(double, double, const struct Map_info *, int, struct bound_box *)
Determines if a point (X,Y) is inside an area outer ring. Islands are not considered.
Definition: Vlib/poly.c:856
plus_t right
Area number to the right, negative for isle.
Definition: dig_structs.h:1526
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
Definition: dig_defines.h:125
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:891
int Vect__get_area_points(const struct Map_info *Map, const plus_t *lines, int n_lines, struct line_pnts *BPoints)
Get area boundary points (internal use only)
struct P_node ** Node
Array of nodes.
Definition: dig_structs.h:883
void dig_free_plus_nodes(struct Plus_head *)
Free Plus->Node structure.
Definition: plus.c:51
plus_t dig_line_get_area(struct Plus_head *, plus_t, int)
Get area number on line side.
Definition: plus_line.c:343
int mode
Access mode.
Definition: dig_structs.h:861
int dig_line_box(const struct line_pnts *, struct bound_box *)
double x
X coordinate.
Definition: dig_structs.h:1453
void dig_cidx_free(struct Plus_head *)
Definition: diglib/cindex.c:44
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
plus_t n_lines
Number of attached lines (size of lines, angle)
Definition: dig_structs.h:1472
int n_values
Number of values in the list.
Definition: gis.h:698
int Vect_check_line_breaks(struct Map_info *, int, struct Map_info *)
Check for and count intersecting lines, do not break.
Definition: break_lines.c:80
#define GV_TOPO_ELEMENT
Native format, topology file.
Definition: dig_defines.h:20
plus_t left
Area number to the left, negative for isle.
Definition: dig_structs.h:1522
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1415
double E
East.
Definition: dig_structs.h:78
int Vect_save_topo(struct Map_info *Map)
Save topology file for vector map.
Definition: build.c:999
struct P_isle ** Isle
Array of isles.
Definition: dig_structs.h:895
plus_t * lines
List of connected lines.
Definition: dig_structs.h:1479
plus_t * isles
1st generation interior islands
Definition: dig_structs.h:1640
#define M_PI
Definition: gis.h:134
plus_t n_isles
Current number of isles.
Definition: dig_structs.h:955
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1628
int level
Topology level.
Definition: dig_structs.h:1313
int Vect_line_prune(struct line_pnts *)
Remove duplicate points, i.e. zero length segments.
Definition: line.c:281
double Vect_line_length(const struct line_pnts *)
Calculate line length, 3D-length in case of 3D vector line.
Definition: line.c:576
#define NULL
Definition: ccmath.h:32
int dig_Wr_spidx(struct gvfile *, struct Plus_head *)
Write spatial index to file.
Definition: spindex_rw.c:1179
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1651
int Vect_open_sidx(struct Map_info *, int)
Open spatial index file (&#39;sidx&#39;)
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:417
plus_t N1
Start node.
Definition: dig_structs.h:1514
int Spidx_built
Spatial index built?
Definition: dig_structs.h:1053
int n_values
Number of items in the list.
Definition: dig_structs.h:1767
#define GV_POINT
Feature types used in memory on run time (may change)
Definition: dig_defines.h:182
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:495
struct bound_box * box
Array of bounding boxes.
Definition: dig_structs.h:1759
void dig_cidx_sort(struct Plus_head *)
#define GV_BUILD_NONE
Topology levels - nothing to build.
Definition: dig_defines.h:123
#define LEVEL_1
Vector level - without topology.
Definition: dig_defines.h:116
plus_t N2
End node.
Definition: dig_structs.h:1503
void dig_spidx_free_nodes(struct Plus_head *)
Free spatial index for nodes.
Definition: spindex.c:107
int Vect_build_ogr(struct Map_info *, int)
Build pseudo-topology (simple features) for OGR layer.
Definition: build_ogr.c:49
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
int Vect_isle_find_area(struct Map_info *Map, int isle, const struct bound_box *box)
Find area outside island.
Definition: build.c:177
plus_t Vect_get_num_primitives(const struct Map_info *, int)
Get number of primitives in vector map.
Definition: level_two.c:47
int dig_write_plus_file(struct gvfile *, struct Plus_head *)
Writes topo structure to topo file.
Definition: plus.c:272
Feature category info.
Definition: dig_structs.h:1702
struct Port_info port
Portability information.
Definition: dig_structs.h:845
#define GV_LINE
Definition: dig_defines.h:183
double N
North.
Definition: dig_structs.h:70
plus_t N1
Start node.
Definition: dig_structs.h:1499
void G_message(const char *,...) __attribute__((format(printf
char type
Line type.
Definition: dig_structs.h:1586
double z
Z coordinate (used only for 3D data)
Definition: dig_structs.h:1461
void dig_spidx_free_isles(struct Plus_head *)
Reset spatial index for isles.
Definition: spindex.c:203
int cidx_up_to_date
Category index to be updated.
Definition: dig_structs.h:1156
int Vect_select_lines_by_box(struct Map_info *, const struct bound_box *, int, struct boxlist *)
Select lines with bounding boxes by box.
Definition: sindex.c:34
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
int with_z
2D/3D vector data
Definition: dig_structs.h:347
Centroid topology.
Definition: dig_structs.h:1532
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1621
struct gvfile spidx_fp
Spatial index file pointer.
Definition: dig_structs.h:1070
int dig_cidx_init(struct Plus_head *)
Initialize Plus_head structure (cidx)
Definition: diglib/cindex.c:29
#define GV_FACE
Definition: dig_defines.h:186
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:220
Basic topology-related info.
Definition: dig_structs.h:784
int Vect_sidx_dump(const struct Map_info *Map, FILE *out)
Dump spatial index to file.
Definition: build.c:1300
int Vect_save_sidx(struct Map_info *Map)
Save spatial index file for vector map.
Definition: build.c:1247
int Vect_build(struct Map_info *Map)
Build topology for vector map.
Definition: build.c:576
double b
Definition: r_raster.c:39
#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
int Vect_build_sidx_from_topo(const struct Map_info *Map)
Create spatial index from topology if necessary (not longer supported)
Definition: build.c:1228
Line topology.
Definition: dig_structs.h:1494
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
#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
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
void * topo
Topology info.
Definition: dig_structs.h:1599
float * angles
List of angles of connected lines.
Definition: dig_structs.h:1488
Boundary topology.
Definition: dig_structs.h:1509
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:726
off_t Vect_write_line(struct Map_info *, int, const struct line_pnts *, const struct line_cats *)
Writes a new feature.
#define GV_BOUNDARY
Definition: dig_defines.h:184
plus_t * lines
List of boundary lines.
Definition: dig_structs.h:1662
#define GV_FORMAT_OGR_DIRECT
OGR format (direct access)
Definition: dig_defines.h:87
double B
Bottom.
Definition: dig_structs.h:90
#define SEP
Definition: build.c:32
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
int Vect_get_area_boundaries(const struct Map_info *, int, struct ilist *)
Creates list of boundaries for given area.
plus_t E[3]
Array of edges.
Definition: dig_structs.h:1549
void dig_file_init(struct gvfile *file)
Initialize gvfile strcuture.
Definition: file.c:170
plus_t Vect_get_num_areas(const struct Map_info *)
Get number of areas in vector map.
Definition: level_two.c:86
#define GPATH_MAX
Definition: gis.h:170
int Vect_area_alive(const struct Map_info *, int)
Check if area is alive or dead (topological level required)
Topological feature - node.
Definition: dig_structs.h:1448
double T
Top.
Definition: dig_structs.h:86
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
struct dig_head head
Header info.
Definition: dig_structs.h:1403
plus_t n_flines
Current number of faces.
Definition: dig_structs.h:918
plus_t n_isles
Number of islands inside.
Definition: dig_structs.h:1632
plus_t left
Volume number to the left, negative for hole.
Definition: dig_structs.h:1553
int Vect_get_isle_area(const struct Map_info *, int)
Returns area id for isle.
int Vect_attach_isle(struct Map_info *Map, int isle, const struct bound_box *box)
(Re)Attach isle to area
Definition: build.c:378
Face topology.
Definition: dig_structs.h:1543
int Vect_find_area(struct Map_info *, double, double)
Find the nearest area.
double y
Y coordinate.
Definition: dig_structs.h:1457
int support_updated
Support files were updated.
Definition: dig_structs.h:1327
Vector map info.
Definition: dig_structs.h:1259
int Vect_topo_check(struct Map_info *Map, struct Map_info *Err)
Extensive tests for correct topology.
Definition: build.c:594
#define PORT_DOUBLE_MAX
Limits for portable types.
Definition: dig_defines.h:66
#define GV_FORMAT_POSTGIS
PostGIS format.
Definition: dig_defines.h:89
plus_t n_llines
Current number of lines.
Definition: dig_structs.h:906
Area (topology) info.
Definition: dig_structs.h:1605
Kernel topology.
Definition: dig_structs.h:1563
FILE * file
File descriptor.
Definition: dig_structs.h:101
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int dig__byte_order_out()
Get byte order.
Definition: portable.c:1013
int temporary
Temporary map flag.
Definition: dig_structs.h:1276
const char * Vect_get_full_name(const struct Map_info *)
Get fully qualified name of vector map.
#define LEVEL_2
Vector level - with 2D topology.
Definition: dig_defines.h:118
List of bounding boxes with id.
Definition: dig_structs.h:1750
void G_warning(const char *,...) __attribute__((format(printf
void dig_spidx_free_lines(struct Plus_head *)
Free spatial index for lines.
Definition: spindex.c:139
double S
South.
Definition: dig_structs.h:74
Definition: path.h:16
struct Port_info spidx_port
Portability information for spatial index.
Definition: dig_structs.h:849
int Vect_line_alive(const struct Map_info *, int)
Check if feature is alive or dead (topological level required)
int Vect_topo_dump(const struct Map_info *Map, FILE *out)
Dump topology to file.
Definition: build.c:1040
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
List of integers.
Definition: gis.h:689
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:914
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 dig_area_del_isle(struct Plus_head *, int, int)
Delete isle from area.
Definition: plus_area.c:307
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:133
plus_t volume
Volume number, negative for duplicate kernel.
Definition: dig_structs.h:1568
#define GV_MODE_WRITE
Write vector map open mode.
Definition: dig_defines.h:106
char * Vect__get_path(char *path, const struct Map_info *Map)
Get map directory name (internal use only)
int * value
Array of values.
Definition: gis.h:694
#define GV_LINES
Definition: dig_defines.h:192
int dig_build_area_with_line(struct Plus_head *, plus_t, int, plus_t **)
Build topo for area from lines.
Definition: plus_area.c:51
void Vect__build_downgrade(struct Map_info *Map, int build)
Downgrade build level (for internal use only)
Definition: build.c:760
struct boxlist * Vect_new_boxlist(int)
Creates and initializes a struct boxlist.
#define GV_SIDX_ELEMENT
Native format, spatial index.
Definition: dig_defines.h:22
void dig_free_plus_isles(struct Plus_head *)
Free Plus->Isle structure.
Definition: plus.c:143
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:910
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
File definition.
Definition: dig_structs.h:96
plus_t N2
End node.
Definition: dig_structs.h:1518
int Vect_get_area_points(const struct Map_info *, int, struct line_pnts *)
Returns polygon array of points (outer ring) of given area.
void void G_verbose_message(const char *,...) __attribute__((format(printf
plus_t n_lines
Number of boundary lines.
Definition: dig_structs.h:1610
int Vect_read_line(const struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
plus_t area
Area it exists w/in, if any.
Definition: dig_structs.h:1669
const char * Vect_get_name(const struct Map_info *)
Get name of vector map.
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_build_sidx(struct Map_info *Map)
Create spatial index if necessary.
Definition: build.c:1208
int Vect_build_partial(struct Map_info *Map, int build)
Build partial topology for vector map.
Definition: build.c:847
int Vect_get_line_areas(const struct Map_info *, int, int *, int *)
Get area id on the left and right side of the boundary.
Definition: level_two.c:350
void dig_free_plus_areas(struct Plus_head *)
Free Plus->Area structure.
Definition: plus.c:115
#define GV_KERNEL
Definition: dig_defines.h:187
void dig_free_plus_lines(struct Plus_head *)
Free Plus->Line structure.
Definition: plus.c:79
int Vect_get_line_type(const struct Map_info *, int)
Get line type.
Definition: level_two.c:258
plus_t n_nodes
Current number of topological features derived from vector geometries.
Definition: dig_structs.h:939
int dig_find_area_poly(struct line_pnts *, double *)
Definition: diglib/poly.c:100