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