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