GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
spindex.c
Go to the documentation of this file.
1/*!
2 \file diglib/spindex.c
3
4 \brief Vector library - spatial index (lower level functions)
5
6 Lower level functions for reading/writing/manipulating vectors.
7
8 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Original author CERL, probably Dave Gerdes
12 \author Update to GRASS 5.7 Radim Blazek
13 \author Update to GRASS 7 Markus Metz
14 */
15
16#include <stdlib.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <unistd.h>
21#include <string.h>
22#include <grass/vector.h>
23#include <grass/glocale.h>
24
25/*!
26 \brief Initit spatial index (nodes, lines, areas, isles)
27
28 \param Plus pointer to Plus_head structure
29
30 \return 1 OK
31 \return 0 on error
32 */
34{
35 int ndims;
36
37 ndims = (Plus->with_z != 0) ? 3 : 2;
38 Plus->spidx_with_z = (Plus->with_z != 0);
39
40 G_debug(1, "dig_spidx_init(), %d dims", ndims);
41
42 if (Plus->Spidx_file) {
43 int fd;
44 char *filename;
45
46 filename = G_tempfile();
47 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
48 Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
49 remove(filename);
50 G_free(filename);
51
52 filename = G_tempfile();
53 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
54 Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
55 remove(filename);
56 G_free(filename);
57
58 filename = G_tempfile();
59 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
60 Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
61 remove(filename);
62 G_free(filename);
63
64 filename = G_tempfile();
65 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
66 Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
67 remove(filename);
68 G_free(filename);
69
70 Plus->Face_spidx = NULL;
71 Plus->Volume_spidx = NULL;
72 Plus->Hole_spidx = NULL;
73
74 if (!Plus->Spidx_new) {
75 close(Plus->Node_spidx->fd);
76 close(Plus->Line_spidx->fd);
77 close(Plus->Area_spidx->fd);
78 close(Plus->Isle_spidx->fd);
79 }
80 }
81 else {
82 Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
83 Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
84 Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
85 Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
86 Plus->Face_spidx = NULL;
87 Plus->Volume_spidx = NULL;
88 Plus->Hole_spidx = NULL;
89 }
90
91 Plus->Node_spidx_offset = 0L;
92 Plus->Line_spidx_offset = 0L;
93 Plus->Area_spidx_offset = 0L;
94 Plus->Isle_spidx_offset = 0L;
95 Plus->Face_spidx_offset = 0L;
96 Plus->Volume_spidx_offset = 0L;
97 Plus->Hole_spidx_offset = 0L;
98
99 Plus->Spidx_built = FALSE;
100
101 return 1;
102}
103
104/*!
105 \brief Free spatial index for nodes
106
107 \param Plus pointer to Plus_head structure
108 */
110{
111 int ndims;
112
113 ndims = Plus->with_z ? 3 : 2;
114
115 /* Node spidx */
116 if (Plus->Node_spidx->fd > -1) {
117 int fd;
118 char *filename;
119
120 if (Plus->Spidx_new)
121 close(Plus->Node_spidx->fd);
122 RTreeDestroyTree(Plus->Node_spidx);
123 filename = G_tempfile();
124 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
125 Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
126 remove(filename);
127 if (!Plus->Spidx_new)
128 close(Plus->Node_spidx->fd);
129 G_free(filename);
130 }
131 else {
132 RTreeDestroyTree(Plus->Node_spidx);
133 Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
134 }
135}
136
137/*!
138 \brief Free spatial index for lines
139
140 \param Plus pointer to Plus_head structure
141 */
143{
144 int ndims;
145
146 ndims = Plus->with_z ? 3 : 2;
147
148 /* Line spidx */
149 if (Plus->Line_spidx->fd > -1) {
150 int fd;
151 char *filename;
152
153 if (Plus->Spidx_new)
154 close(Plus->Line_spidx->fd);
155 RTreeDestroyTree(Plus->Line_spidx);
156 filename = G_tempfile();
157 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
158 Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
159 remove(filename);
160 if (!Plus->Spidx_new)
161 close(Plus->Line_spidx->fd);
162 G_free(filename);
163 }
164 else {
165 RTreeDestroyTree(Plus->Line_spidx);
166 Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
167 }
168}
169
170/*!
171 \brief Reset spatial index for areas
172
173 \param Plus pointer to Plus_head structure
174 */
176{
177 int ndims;
178
179 ndims = Plus->with_z ? 3 : 2;
180
181 /* Area spidx */
182 if (Plus->Area_spidx->fd > -1) {
183 int fd;
184 char *filename;
185
186 if (Plus->Spidx_new)
187 close(Plus->Area_spidx->fd);
188 RTreeDestroyTree(Plus->Area_spidx);
189 filename = G_tempfile();
190 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
191 Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
192 remove(filename);
193 if (!Plus->Spidx_new)
194 close(Plus->Area_spidx->fd);
195 G_free(filename);
196 }
197 else {
198 RTreeDestroyTree(Plus->Area_spidx);
199 Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
200 }
201}
202
203/*!
204 \brief Reset spatial index for isles
205
206 \param Plus pointer to Plus_head structure
207 */
209{
210 int ndims;
211
212 ndims = Plus->with_z ? 3 : 2;
213
214 /* Isle spidx */
215 if (Plus->Isle_spidx->fd > -1) {
216 int fd;
217 char *filename;
218
219 if (Plus->Spidx_new)
220 close(Plus->Isle_spidx->fd);
221 RTreeDestroyTree(Plus->Isle_spidx);
222 filename = G_tempfile();
223 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
224 Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
225 remove(filename);
226 if (!Plus->Spidx_new)
227 close(Plus->Isle_spidx->fd);
228 G_free(filename);
229 }
230 else {
231 RTreeDestroyTree(Plus->Isle_spidx);
232 Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
233 }
234}
235
236/*!
237 \brief Free spatial index (nodes, lines, areas, isles)
238
239 \param Plus pointer to Plus_head structure
240 */
242{
243 /* close tmp files */
244 if (Plus->Spidx_new) {
245 /* Node spidx */
246 if (Plus->Node_spidx->fd > -1)
247 close(Plus->Node_spidx->fd);
248 /* Line spidx */
249 if (Plus->Spidx_new && Plus->Line_spidx->fd > -1)
250 close(Plus->Line_spidx->fd);
251 /* Area spidx */
252 if (Plus->Area_spidx->fd > -1)
253 close(Plus->Area_spidx->fd);
254 /* Isle spidx */
255 if (Plus->Isle_spidx->fd > -1)
256 close(Plus->Isle_spidx->fd);
257 }
258
259 /* destroy tree structures */
260 /* Node spidx */
261 if (Plus->Node_spidx)
262 RTreeDestroyTree(Plus->Node_spidx);
263 /* Line spidx */
264 if (Plus->Line_spidx)
265 RTreeDestroyTree(Plus->Line_spidx);
266 /* Area spidx */
267 if (Plus->Area_spidx)
268 RTreeDestroyTree(Plus->Area_spidx);
269 /* Isle spidx */
270 if (Plus->Isle_spidx)
271 RTreeDestroyTree(Plus->Isle_spidx);
272
273 /* 3D future : */
274 /* Face spidx */
275 /* Volume spidx */
276 /* Hole spidx */
277}
278
279/*!
280 \brief Add new node to spatial index
281
282 \param Plus pointer to Plus_head structure
283 \param node node id
284 \param x,y,z node coordinates
285
286 \return 1 OK
287 \return 0 on error
288 */
289int dig_spidx_add_node(struct Plus_head *Plus, int node, double x, double y,
290 double z)
291{
292 static struct RTree_Rect rect;
293 static int rect_init = 0;
294
295 if (!rect_init) {
296 /* always 6 sides for 3D */
297 rect.boundary = G_malloc(6 * sizeof(RectReal));
298 rect_init = 6;
299 }
300
301 G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
302 y, z);
303
304 rect.boundary[0] = x;
305 rect.boundary[1] = y;
306 rect.boundary[2] = z;
307 rect.boundary[3] = x;
308 rect.boundary[4] = y;
309 rect.boundary[5] = z;
310 RTreeInsertRect(&rect, node, Plus->Node_spidx);
311
312 return 1;
313}
314
315/*!
316 \brief Add new line to spatial index
317
318 \param Plus pointer to Plus_head structure
319 \param line line id
320 \param box bounding box
321
322 \return 0
323 */
324int dig_spidx_add_line(struct Plus_head *Plus, int line,
325 const struct bound_box *box)
326{
327 static struct RTree_Rect rect;
328 static int rect_init = 0;
329
330 if (!rect_init) {
331 /* always 6 sides for 3D */
332 rect.boundary = G_malloc(6 * sizeof(RectReal));
333 rect_init = 6;
334 }
335
336 G_debug(3, "dig_spidx_add_line(): line = %d", line);
337
338 rect.boundary[0] = box->W;
339 rect.boundary[1] = box->S;
340 rect.boundary[2] = box->B;
341 rect.boundary[3] = box->E;
342 rect.boundary[4] = box->N;
343 rect.boundary[5] = box->T;
344 RTreeInsertRect(&rect, line, Plus->Line_spidx);
345
346 return 0;
347}
348
349/*!
350 \brief Add new area to spatial index
351
352 \param Plus pointer to Plus_head structure
353 \param area area id
354 \param box bounding box
355
356 \return 0
357 */
358int dig_spidx_add_area(struct Plus_head *Plus, int area,
359 const struct bound_box *box)
360{
361 static struct RTree_Rect rect;
362 static int rect_init = 0;
363
364 if (!rect_init) {
365 /* always 6 sides for 3D */
366 rect.boundary = G_malloc(6 * sizeof(RectReal));
367 rect_init = 6;
368 }
369
370 G_debug(3, "dig_spidx_add_area(): area = %d", area);
371
372 rect.boundary[0] = box->W;
373 rect.boundary[1] = box->S;
374 rect.boundary[2] = box->B;
375 rect.boundary[3] = box->E;
376 rect.boundary[4] = box->N;
377 rect.boundary[5] = box->T;
378 RTreeInsertRect(&rect, area, Plus->Area_spidx);
379
380 return 0;
381}
382
383/*!
384 \brief Add new island to spatial index
385
386 \param Plus pointer to Plus_head structure
387 \param isle isle id
388 \param box bounding box
389
390 \return 0
391 */
393 const struct bound_box *box)
394{
395 static struct RTree_Rect rect;
396 static int rect_init = 0;
397
398 if (!rect_init) {
399 /* always 6 sides for 3D */
400 rect.boundary = G_malloc(6 * sizeof(RectReal));
401 rect_init = 6;
402 }
403
404 G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
405
406 rect.boundary[0] = box->W;
407 rect.boundary[1] = box->S;
408 rect.boundary[2] = box->B;
409 rect.boundary[3] = box->E;
410 rect.boundary[4] = box->N;
411 rect.boundary[5] = box->T;
412 RTreeInsertRect(&rect, isle, Plus->Isle_spidx);
413
414 return 0;
415}
416
417/*!
418 \brief Delete node from spatial index
419
420 G_fatal_error() called on error.
421
422 \param Plus pointer to Plus_head structure
423 \param node node id
424
425 \return 0
426 */
427int dig_spidx_del_node(struct Plus_head *Plus, int node)
428{
429 int ret;
430 struct P_node *Node;
431 static struct RTree_Rect rect;
432 static int rect_init = 0;
433
434 if (!rect_init) {
435 /* always 6 sides for 3D */
436 rect.boundary = G_malloc(6 * sizeof(RectReal));
437 rect_init = 6;
438 }
439
440 G_debug(3, "dig_spidx_del_node(): node = %d", node);
441
442 Node = Plus->Node[node];
443
444 rect.boundary[0] = Node->x;
445 rect.boundary[1] = Node->y;
446 rect.boundary[2] = Node->z;
447 rect.boundary[3] = Node->x;
448 rect.boundary[4] = Node->y;
449 rect.boundary[5] = Node->z;
450
451 ret = RTreeDeleteRect(&rect, node, Plus->Node_spidx);
452
453 if (ret)
454 G_fatal_error(_("Unable to delete node %d from spatial index"), node);
455
456 return 0;
457}
458
459/*!
460 \brief Delete line from spatial index
461
462 G_fatal_error() called on error.
463
464 \param Plus pointer to Plus_head structure
465 \param line line id
466 \param x,y,z coordinates
467
468 \return 0
469 */
470int dig_spidx_del_line(struct Plus_head *Plus, int line, double x, double y,
471 double z)
472{
473 int ret;
474 static struct RTree_Rect rect;
475 static int rect_init = 0;
476
477 if (!rect_init) {
478 /* always 6 sides for 3D */
479 rect.boundary = G_malloc(6 * sizeof(RectReal));
480 rect_init = 6;
481 }
482
483 G_debug(3, "dig_spidx_del_line(): line = %d", line);
484
485 rect.boundary[0] = x;
486 rect.boundary[1] = y;
487 rect.boundary[2] = z;
488 rect.boundary[3] = x;
489 rect.boundary[4] = y;
490 rect.boundary[5] = z;
491
492 ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
493
494 G_debug(3, " ret = %d", ret);
495
496 if (ret)
497 G_fatal_error(_("Unable to delete line %d from spatial index"), line);
498
499 return 0;
500}
501
502/*!
503 \brief Delete area from spatial index
504
505 G_fatal_error() called on error.
506
507 \param Plus pointer to Plus_head structure
508 \param area area id
509
510 \return 0
511 */
512int dig_spidx_del_area(struct Plus_head *Plus, int area)
513{
514 int ret;
515 struct P_area *Area;
516 struct P_line *Line;
517 struct P_node *Node;
518 struct P_topo_b *topo;
519 static struct RTree_Rect rect;
520 static int rect_init = 0;
521
522 if (!rect_init) {
523 /* always 6 sides for 3D */
524 rect.boundary = G_malloc(6 * sizeof(RectReal));
525 rect_init = 6;
526 }
527
528 G_debug(3, "dig_spidx_del_area(): area = %d", area);
529
530 Area = Plus->Area[area];
531
532 if (Area == NULL) {
533 G_fatal_error(_("Attempt to delete sidx for dead area"));
534 }
535
536 Line = Plus->Line[abs(Area->lines[0])];
537 topo = (struct P_topo_b *)Line->topo;
538 Node = Plus->Node[topo->N1];
539
540 rect.boundary[0] = Node->x;
541 rect.boundary[1] = Node->y;
542 rect.boundary[2] = Node->z;
543 rect.boundary[3] = Node->x;
544 rect.boundary[4] = Node->y;
545 rect.boundary[5] = Node->z;
546
547 ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
548
549 if (ret)
550 G_fatal_error(_("Unable to delete area %d from spatial index"), area);
551
552 return 0;
553}
554
555/*!
556 \brief Delete isle from spatial index
557
558 G_fatal_error() called on error.
559
560 \param Plus pointer to Plus_head structure
561 \param isle isle id
562
563 \return 0
564 */
566{
567 int ret;
568 struct P_isle *Isle;
569 struct P_line *Line;
570 struct P_node *Node;
571 struct P_topo_b *topo;
572 static struct RTree_Rect rect;
573 static int rect_init = 0;
574
575 if (!rect_init) {
576 /* always 6 sides for 3D */
577 rect.boundary = G_malloc(6 * sizeof(RectReal));
578 rect_init = 6;
579 }
580
581 G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
582
583 Isle = Plus->Isle[isle];
584
585 Line = Plus->Line[abs(Isle->lines[0])];
586 topo = (struct P_topo_b *)Line->topo;
587 Node = Plus->Node[topo->N1];
588
589 rect.boundary[0] = Node->x;
590 rect.boundary[1] = Node->y;
591 rect.boundary[2] = Node->z;
592 rect.boundary[3] = Node->x;
593 rect.boundary[4] = Node->y;
594 rect.boundary[5] = Node->z;
595
596 ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
597
598 if (ret)
599 G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
600
601 return 0;
602}
603
604/* This function is called by RTreeSearch() to add selected node/line/area/isle
605 * to the list */
606static int _add_item(int id, const struct RTree_Rect *rect G_UNUSED,
607 struct ilist *list)
608{
609 G_ilist_add(list, id);
610 return 1;
611}
612
613/* This function is called by RTreeSearch() to add
614 * selected node/line/area/isle to the box list */
615static int _add_item_with_box(int id, const struct RTree_Rect *rect,
616 struct boxlist *list)
617{
618 struct bound_box box;
619
620 box.W = rect->boundary[0];
621 box.S = rect->boundary[1];
622 box.B = rect->boundary[2];
623 box.E = rect->boundary[3];
624 box.N = rect->boundary[4];
625 box.T = rect->boundary[5];
626
627 dig_boxlist_add(list, id, &box);
628 return 1;
629}
630
631struct boxid {
632 int id;
633 struct bound_box *box;
634};
635
636/* This function is called by RTreeSearch() to add
637 * selected node/line/area/isle to the box list */
638static int _set_item_box(int id, const struct RTree_Rect *rect,
639 struct boxid *box_id)
640{
641 if (id == box_id->id) {
642
643 box_id->box->W = rect->boundary[0];
644 box_id->box->S = rect->boundary[1];
645 box_id->box->B = rect->boundary[2];
646 box_id->box->E = rect->boundary[3];
647 box_id->box->N = rect->boundary[4];
648 box_id->box->T = rect->boundary[5];
649
650 return 0;
651 }
652
653 return 1;
654}
655
656/*!
657 \brief Select nodes by bbox
658
659 \param Plus pointer to Plus_head structure
660 \param box bounding box
661 \param list list of selected lines
662
663 \return number of selected nodes
664 \return -1 on error
665 */
666int dig_select_nodes(struct Plus_head *Plus, const struct bound_box *box,
667 struct ilist *list)
668{
669 static struct RTree_Rect rect;
670 static int rect_init = 0;
671
672 if (!rect_init) {
673 /* always 6 sides for 3D */
674 rect.boundary = G_malloc(6 * sizeof(RectReal));
675 rect_init = 6;
676 }
677
678 G_debug(3, "dig_select_nodes()");
679
680 list->n_values = 0;
681
682 rect.boundary[0] = box->W;
683 rect.boundary[1] = box->S;
684 rect.boundary[2] = box->B;
685 rect.boundary[3] = box->E;
686 rect.boundary[4] = box->N;
687 rect.boundary[5] = box->T;
688
689 if (Plus->Spidx_new)
690 RTreeSearch(Plus->Node_spidx, &rect, (SearchHitCallback *)_add_item,
691 list);
692 else
693 rtree_search(Plus->Node_spidx, &rect, (SearchHitCallback *)_add_item,
694 list, Plus);
695
696 return (list->n_values);
697}
698
699/* This function is called by RTreeSearch() for nodes to find the node id */
700static int _add_node(int id, const struct RTree_Rect *rect G_UNUSED, int *node)
701{
702 *node = id;
703 return 0;
704}
705
706/*!
707 \brief Find one node by coordinates
708
709 \param Plus pointer to Plus_head structure
710 \param x,y,z coordinates
711
712 \return number of node
713 \return 0 not found
714 */
715int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
716{
717 int node;
718 static struct RTree_Rect rect;
719 static int rect_init = 0;
720
721 if (!rect_init) {
722 /* always 6 sides for 3D */
723 rect.boundary = G_malloc(6 * sizeof(RectReal));
724 rect_init = 6;
725 }
726
727 G_debug(3, "dig_find_node()");
728
729 rect.boundary[0] = x;
730 rect.boundary[1] = y;
731 rect.boundary[2] = z;
732 rect.boundary[3] = x;
733 rect.boundary[4] = y;
734 rect.boundary[5] = z;
735
736 node = 0;
737 if (Plus->Spidx_new)
738 RTreeSearch(Plus->Node_spidx, &rect, (SearchHitCallback *)_add_node,
739 &node);
740 else
741 rtree_search(Plus->Node_spidx, &rect, (SearchHitCallback *)_add_node,
742 &node, Plus);
743
744 return node;
745}
746
747/*!
748 \brief Select lines with boxes by box
749
750 \param Plus pointer to Plus_head structure
751 \param box bounding box
752 \param list boxlist of selected lines
753
754 \return number of selected lines
755 \return 0 not found
756 */
757int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
758 struct boxlist *list)
759{
760 static struct RTree_Rect rect;
761 static int rect_init = 0;
762
763 if (!rect_init) {
764 /* always 6 sides for 3D */
765 rect.boundary = G_malloc(6 * sizeof(RectReal));
766 rect_init = 6;
767 }
768
769 G_debug(3, "dig_select_lines_with_box()");
770
771 list->n_values = 0;
772
773 rect.boundary[0] = box->W;
774 rect.boundary[1] = box->S;
775 rect.boundary[2] = box->B;
776 rect.boundary[3] = box->E;
777 rect.boundary[4] = box->N;
778 rect.boundary[5] = box->T;
779
780 if (Plus->Spidx_new)
781 RTreeSearch(Plus->Line_spidx, &rect,
782 (SearchHitCallback *)_add_item_with_box, list);
783 else
784 rtree_search(Plus->Line_spidx, &rect,
785 (SearchHitCallback *)_add_item_with_box, list, Plus);
786
787 return (list->n_values);
788}
789
790/*!
791 \brief Find box for line
792
793 \param Plus pointer to Plus_head structure
794 \param line line id
795 \param[out] box bounding box
796
797 \return > 0 bounding box for line found
798 \return 0 not found
799 */
800int dig_find_line_box(struct Plus_head *Plus, int line, struct bound_box *box)
801{
802 int ret, type;
803 struct P_line *Line;
804 struct boxid box_id;
805 static struct RTree_Rect rect;
806 static int rect_init = 0;
807
808 G_debug(3, "dig_find_line_box()");
809
810 if (!rect_init) {
811 /* always 6 sides for 3D */
812 rect.boundary = G_malloc(6 * sizeof(RectReal));
813 rect_init = 6;
814 }
815
816 Line = Plus->Line[line];
817 type = Line->type;
818
819 /* GV_LINES: retrieve box from spatial index */
820 if (type & GV_LINES) {
821 struct P_node *Node = NULL;
822
823 if (type == GV_LINE) {
824 struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
825
826 Node = Plus->Node[topo->N1];
827 }
828 else if (type == GV_BOUNDARY) {
829 struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
830
831 Node = Plus->Node[topo->N1];
832 }
833
834 rect.boundary[0] = Node->x;
835 rect.boundary[1] = Node->y;
836 rect.boundary[2] = Node->z;
837 rect.boundary[3] = Node->x;
838 rect.boundary[4] = Node->y;
839 rect.boundary[5] = Node->z;
840
841 box_id.id = line;
842 box_id.box = box;
843
844 if (Plus->Spidx_new)
845 ret = RTreeSearch(Plus->Line_spidx, &rect,
846 (SearchHitCallback *)_set_item_box, &box_id);
847 else
848 ret =
849 rtree_search(Plus->Line_spidx, &rect,
850 (SearchHitCallback *)_set_item_box, &box_id, Plus);
851
852 return ret;
853 }
854
855 /* do not translate this error because
856 * 1. this error is not supposed to happen
857 * 2. the maintainer at which this message is directed prefers english */
858 G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for "
859 "lines and boundaries.");
860
861 return 0;
862}
863
864/*!
865 \brief Select areas with boxes by box
866
867 \param Plus pointer to Plus_head structure
868 \param box bounding box
869 \param list boxlist of selected areas
870
871 \return number of selected areas
872 */
873int dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
874 struct boxlist *list)
875{
876 static struct RTree_Rect rect;
877 static int rect_init = 0;
878
879 if (!rect_init) {
880 /* always 6 sides for 3D */
881 rect.boundary = G_malloc(6 * sizeof(RectReal));
882 rect_init = 6;
883 }
884
885 G_debug(3, "dig_select_areas_with_box()");
886
887 list->n_values = 0;
888
889 rect.boundary[0] = box->W;
890 rect.boundary[1] = box->S;
891 rect.boundary[2] = box->B;
892 rect.boundary[3] = box->E;
893 rect.boundary[4] = box->N;
894 rect.boundary[5] = box->T;
895
896 if (Plus->Spidx_new)
897 RTreeSearch(Plus->Area_spidx, &rect,
898 (SearchHitCallback *)_add_item_with_box, list);
899 else
900 rtree_search(Plus->Area_spidx, &rect,
901 (SearchHitCallback *)_add_item_with_box, list, Plus);
902
903 return (list->n_values);
904}
905
906/*!
907 \brief Find bounding box for given area
908
909 \param Plus pointer to Plus_head structure
910 \param area area id
911 \param[out] box bounding box
912
913 \return > 0 bounding box for area found
914 \return 0 not found
915 */
916int dig_find_area_box(struct Plus_head *Plus, int area, struct bound_box *box)
917{
918 int ret;
919 struct boxid box_id;
920 struct P_area *Area;
921 struct P_line *Line;
922 struct P_node *Node;
923 struct P_topo_b *topo;
924 static struct RTree_Rect rect;
925 static int rect_init = 0;
926
927 G_debug(3, "dig_find_area_box()");
928
929 if (!rect_init) {
930 /* always 6 sides for 3D */
931 rect.boundary = G_malloc(6 * sizeof(RectReal));
932 rect_init = 6;
933 }
934
935 Area = Plus->Area[area];
936 Line = Plus->Line[abs(Area->lines[0])];
937 topo = (struct P_topo_b *)Line->topo;
938 Node = Plus->Node[topo->N1];
939
940 rect.boundary[0] = Node->x;
941 rect.boundary[1] = Node->y;
942 rect.boundary[2] = Node->z;
943 rect.boundary[3] = Node->x;
944 rect.boundary[4] = Node->y;
945 rect.boundary[5] = Node->z;
946
947 box_id.id = area;
948 box_id.box = box;
949
950 if (Plus->Spidx_new)
951 ret = RTreeSearch(Plus->Area_spidx, &rect,
952 (SearchHitCallback *)_set_item_box, &box_id);
953 else
954 ret = rtree_search(Plus->Area_spidx, &rect,
955 (SearchHitCallback *)_set_item_box, &box_id, Plus);
956
957 return ret;
958}
959
960/*!
961 \brief Select isles with boxes by box
962
963 \param Plus pointer to Plus_head structure
964 \param box bounding box
965 \param list boxlist of selected isles
966
967 \return number of selected isles
968 */
969int dig_select_isles(struct Plus_head *Plus, const struct bound_box *box,
970 struct boxlist *list)
971{
972 static struct RTree_Rect rect;
973 static int rect_init = 0;
974
975 if (!rect_init) {
976 /* always 6 sides for 3D */
977 rect.boundary = G_malloc(6 * sizeof(RectReal));
978 rect_init = 6;
979 }
980
981 G_debug(3, "dig_select_areas_with_box()");
982
983 list->n_values = 0;
984
985 rect.boundary[0] = box->W;
986 rect.boundary[1] = box->S;
987 rect.boundary[2] = box->B;
988 rect.boundary[3] = box->E;
989 rect.boundary[4] = box->N;
990 rect.boundary[5] = box->T;
991
992 if (Plus->Spidx_new)
993 RTreeSearch(Plus->Isle_spidx, &rect,
994 (SearchHitCallback *)_add_item_with_box, list);
995 else
996 rtree_search(Plus->Isle_spidx, &rect,
997 (SearchHitCallback *)_add_item_with_box, list, Plus);
998
999 return (list->n_values);
1000}
1001
1002/*!
1003 \brief Find box for isle
1004
1005 \param Plus pointer to Plus_head structure
1006 \param isle isle id
1007 \param[out] box bounding box
1008
1009 \return > 0 bounding box for isle found
1010 \return 0 not found
1011 */
1012int dig_find_isle_box(struct Plus_head *Plus, int isle, struct bound_box *box)
1013{
1014 int ret;
1015 struct boxid box_id;
1016 struct P_isle *Isle;
1017 struct P_line *Line;
1018 struct P_node *Node;
1019 struct P_topo_b *topo;
1020 static struct RTree_Rect rect;
1021 static int rect_init = 0;
1022
1023 G_debug(3, "dig_find_isle_box()");
1024
1025 if (!rect_init) {
1026 /* always 6 sides for 3D */
1027 rect.boundary = G_malloc(6 * sizeof(RectReal));
1028 rect_init = 6;
1029 }
1030
1031 Isle = Plus->Isle[isle];
1032 Line = Plus->Line[abs(Isle->lines[0])];
1033 topo = (struct P_topo_b *)Line->topo;
1034 Node = Plus->Node[topo->N1];
1035
1036 rect.boundary[0] = Node->x;
1037 rect.boundary[1] = Node->y;
1038 rect.boundary[2] = Node->z;
1039 rect.boundary[3] = Node->x;
1040 rect.boundary[4] = Node->y;
1041 rect.boundary[5] = Node->z;
1042
1043 box_id.id = isle;
1044 box_id.box = box;
1045
1046 if (Plus->Spidx_new)
1047 ret = RTreeSearch(Plus->Isle_spidx, &rect,
1048 (SearchHitCallback *)_set_item_box, &box_id);
1049 else
1050 ret = rtree_search(Plus->Isle_spidx, &rect,
1051 (SearchHitCallback *)_set_item_box, &box_id, Plus);
1052
1053 return ret;
1054}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
char * G_tempfile(void)
Returns a temporary file name.
Definition tempfile.c:60
void G_ilist_add(struct ilist *, int)
Add item to ilist.
Definition ilist.c:75
int G_debug(int, const char *,...) __attribute__((format(printf
#define GV_LINE
#define GV_LINES
#define GV_BOUNDARY
int rtree_search(struct RTree *, struct RTree_Rect *, SearchHitCallback, void *, struct Plus_head *)
Search spatial index file Can't use regular RTreeSearch() here because sidx must be read with dig__fr...
int dig_boxlist_add(struct boxlist *, int, const struct bound_box *)
Header file for msvc/fcntl.c.
#define open
Definition fcntl.h:32
#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 _(str)
Definition glocale.h:10
int SearchHitCallback(int id, const struct RTree_Rect *rect, void *arg)
Definition rtree.h:83
int dig_select_isles(struct Plus_head *Plus, const struct bound_box *box, struct boxlist *list)
Select isles with boxes by box.
Definition spindex.c:969
int dig_spidx_del_area(struct Plus_head *Plus, int area)
Delete area from spatial index.
Definition spindex.c:512
void dig_spidx_free_areas(struct Plus_head *Plus)
Reset spatial index for areas.
Definition spindex.c:175
int dig_spidx_add_line(struct Plus_head *Plus, int line, const struct bound_box *box)
Add new line to spatial index.
Definition spindex.c:324
int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
Delete isle from spatial index.
Definition spindex.c:565
int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
Find one node by coordinates.
Definition spindex.c:715
int dig_find_isle_box(struct Plus_head *Plus, int isle, struct bound_box *box)
Find box for isle.
Definition spindex.c:1012
void dig_spidx_free_lines(struct Plus_head *Plus)
Free spatial index for lines.
Definition spindex.c:142
int dig_select_areas(struct Plus_head *Plus, const struct bound_box *box, struct boxlist *list)
Select areas with boxes by box.
Definition spindex.c:873
int dig_spidx_add_node(struct Plus_head *Plus, int node, double x, double y, double z)
Add new node to spatial index.
Definition spindex.c:289
int dig_select_nodes(struct Plus_head *Plus, const struct bound_box *box, struct ilist *list)
Select nodes by bbox.
Definition spindex.c:666
void dig_spidx_free_isles(struct Plus_head *Plus)
Reset spatial index for isles.
Definition spindex.c:208
void dig_spidx_free_nodes(struct Plus_head *Plus)
Free spatial index for nodes.
Definition spindex.c:109
int dig_spidx_add_area(struct Plus_head *Plus, int area, const struct bound_box *box)
Add new area to spatial index.
Definition spindex.c:358
int dig_spidx_del_node(struct Plus_head *Plus, int node)
Delete node from spatial index.
Definition spindex.c:427
int dig_spidx_del_line(struct Plus_head *Plus, int line, double x, double y, double z)
Delete line from spatial index.
Definition spindex.c:470
int dig_find_line_box(struct Plus_head *Plus, int line, struct bound_box *box)
Find box for line.
Definition spindex.c:800
void dig_spidx_free(struct Plus_head *Plus)
Free spatial index (nodes, lines, areas, isles)
Definition spindex.c:241
int dig_spidx_init(struct Plus_head *Plus)
Initit spatial index (nodes, lines, areas, isles)
Definition spindex.c:33
int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box, struct boxlist *list)
Select lines with boxes by box.
Definition spindex.c:757
int dig_find_area_box(struct Plus_head *Plus, int area, struct bound_box *box)
Find bounding box for given area.
Definition spindex.c:916
int dig_spidx_add_isle(struct Plus_head *Plus, int isle, const struct bound_box *box)
Add new island to spatial index.
Definition spindex.c:392
Area (topology) info.
plus_t * lines
List of boundary lines.
Isle (topology) info.
plus_t * lines
List of boundary lines.
Vector geometry.
char type
Line type.
void * topo
Topology info.
Topological feature - node.
double x
X coordinate.
double z
Z coordinate (used only for 3D data)
double y
Y coordinate.
Boundary topology.
plus_t N1
Start node.
Line topology.
plus_t N1
Start node.
Basic topology-related info.
RectReal * boundary
Definition rtree.h:52
Bounding box.
Definition dig_structs.h:62
double W
West.
Definition dig_structs.h:78
double T
Top.
Definition dig_structs.h:82
double S
South.
Definition dig_structs.h:70
double N
North.
Definition dig_structs.h:66
double E
East.
Definition dig_structs.h:74
double B
Bottom.
Definition dig_structs.h:86
List of bounding boxes with id.
List of integers.
Definition gis.h:712
Definition manage.h:4
#define close
Definition unistd.h:8
int RTreeDeleteRect(struct RTree_Rect *r, int tid, struct RTree *t)
Delete an item from a R*-Tree.
struct RTree * RTreeCreateTree(int fd, off_t rootpos, int ndims)
Create new empty R*-Tree.
int RTreeInsertRect(struct RTree_Rect *r, int tid, struct RTree *t)
Insert an item into a R*-Tree.
void RTreeDestroyTree(struct RTree *t)
Destroy an R*-Tree.
int RTreeSearch(struct RTree *t, struct RTree_Rect *r, SearchHitCallback *shcb, void *cbarg)
Search an R*-Tree.
#define x