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