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