31
35
int dig_spidx_init(struct Plus_head *Plus)
34
G_debug(1, "dig_spidx_init()");
36
Plus->Node_spidx = RTreeNewIndex();
37
Plus->Line_spidx = RTreeNewIndex();
38
Plus->Area_spidx = RTreeNewIndex();
39
Plus->Isle_spidx = RTreeNewIndex();
39
ndims = (Plus->with_z != 0) ? 3 : 2;
40
Plus->spidx_with_z = (Plus->with_z != 0);
42
G_debug(1, "dig_spidx_init(), %d dims", ndims);
44
if (Plus->Spidx_file) {
48
filename = G_tempfile();
49
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
50
Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
53
filename = G_tempfile();
54
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
55
Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
58
filename = G_tempfile();
59
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
60
Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
63
filename = G_tempfile();
64
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
65
Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
68
Plus->Face_spidx = NULL;
69
Plus->Volume_spidx = NULL;
70
Plus->Hole_spidx = NULL;
72
if (!Plus->Spidx_new) {
73
close(Plus->Node_spidx->fd);
74
close(Plus->Line_spidx->fd);
75
close(Plus->Area_spidx->fd);
76
close(Plus->Isle_spidx->fd);
80
Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
81
Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
82
Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
83
Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
84
Plus->Face_spidx = NULL;
85
Plus->Volume_spidx = NULL;
86
Plus->Hole_spidx = NULL;
41
89
Plus->Node_spidx_offset = 0L;
42
Plus->Edge_spidx_offset = 0L;
43
90
Plus->Line_spidx_offset = 0L;
44
91
Plus->Area_spidx_offset = 0L;
45
92
Plus->Isle_spidx_offset = 0L;
93
Plus->Face_spidx_offset = 0L;
46
94
Plus->Volume_spidx_offset = 0L;
47
95
Plus->Hole_spidx_offset = 0L;
97
Plus->Spidx_built = FALSE;
53
103
\brief Free spatial index for nodes
55
105
\param Plus pointer to Plus_head structure
57
107
void dig_spidx_free_nodes(struct Plus_head *Plus)
59
RTreeDestroyNode(Plus->Node_spidx);
60
Plus->Node_spidx = RTreeNewIndex();
111
ndims = Plus->with_z ? 3 : 2;
114
if (Plus->Node_spidx->fd > -1) {
119
close(Plus->Node_spidx->fd);
120
RTreeDestroyTree(Plus->Node_spidx);
121
filename = G_tempfile();
122
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
123
Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
125
if (!Plus->Spidx_new)
126
close(Plus->Node_spidx->fd);
129
RTreeDestroyTree(Plus->Node_spidx);
130
Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
64
135
\brief Free spatial index for lines
66
137
\param Plus pointer to Plus_head structure
68
139
void dig_spidx_free_lines(struct Plus_head *Plus)
70
RTreeDestroyNode(Plus->Line_spidx);
71
Plus->Line_spidx = RTreeNewIndex();
143
ndims = Plus->with_z ? 3 : 2;
146
if (Plus->Line_spidx->fd > -1) {
151
close(Plus->Line_spidx->fd);
152
RTreeDestroyTree(Plus->Line_spidx);
153
filename = G_tempfile();
154
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
155
Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
157
if (!Plus->Spidx_new)
158
close(Plus->Line_spidx->fd);
161
RTreeDestroyTree(Plus->Line_spidx);
162
Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
75
\brief Free spatial index for areas
167
\brief Reset spatial index for areas
77
169
\param Plus pointer to Plus_head structure
79
171
void dig_spidx_free_areas(struct Plus_head *Plus)
81
RTreeDestroyNode(Plus->Area_spidx);
82
Plus->Area_spidx = RTreeNewIndex();
175
ndims = Plus->with_z ? 3 : 2;
178
if (Plus->Area_spidx->fd > -1) {
183
close(Plus->Area_spidx->fd);
184
RTreeDestroyTree(Plus->Area_spidx);
185
filename = G_tempfile();
186
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
187
Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
189
if (!Plus->Spidx_new)
190
close(Plus->Area_spidx->fd);
193
RTreeDestroyTree(Plus->Area_spidx);
194
Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
86
\brief Free spatial index for isles
199
\brief Reset spatial index for isles
88
201
\param Plus pointer to Plus_head structure
90
203
void dig_spidx_free_isles(struct Plus_head *Plus)
92
RTreeDestroyNode(Plus->Isle_spidx);
93
Plus->Isle_spidx = RTreeNewIndex();
207
ndims = Plus->with_z ? 3 : 2;
210
if (Plus->Isle_spidx->fd > -1) {
215
close(Plus->Isle_spidx->fd);
216
RTreeDestroyTree(Plus->Isle_spidx);
217
filename = G_tempfile();
218
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
219
Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
221
if (!Plus->Spidx_new)
222
close(Plus->Isle_spidx->fd);
225
RTreeDestroyTree(Plus->Isle_spidx);
226
Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
258
460
\param Plus pointer to Plus_head structure
259
461
\param line line id
462
\param x,y,z coordinates
263
int dig_spidx_del_line(struct Plus_head *Plus, int line)
466
int dig_spidx_del_line(struct Plus_head *Plus, int line,
467
double x, double y, double z)
470
static struct RTree_Rect rect;
471
static int rect_init = 0;
474
/* always 6 sides for 3D */
475
rect.boundary = G_malloc(6 * sizeof(RectReal));
269
479
G_debug(3, "dig_spidx_del_line(): line = %d", line);
271
Line = Plus->Line[line];
273
G_debug(3, " box(x1,y1,z1,x2,y2,z2): %f %f %f %f %f %f", Line->W,
274
Line->S, Line->B, Line->E, Line->N, Line->T);
276
rect.boundary[0] = Line->W;
277
rect.boundary[1] = Line->S;
278
rect.boundary[2] = Line->B;
279
rect.boundary[3] = Line->E;
280
rect.boundary[4] = Line->N;
281
rect.boundary[5] = Line->T;
283
ret = RTreeDeleteRect(&rect, line, &(Plus->Line_spidx));
481
rect.boundary[0] = x;
482
rect.boundary[1] = y;
483
rect.boundary[2] = z;
484
rect.boundary[3] = x;
485
rect.boundary[4] = y;
486
rect.boundary[5] = z;
488
ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
285
490
G_debug(3, " ret = %d", ret);
314
529
G_fatal_error(_("Attempt to delete sidx for dead area"));
317
rect.boundary[0] = Area->W;
318
rect.boundary[1] = Area->S;
319
rect.boundary[2] = Area->B;
320
rect.boundary[3] = Area->E;
321
rect.boundary[4] = Area->N;
322
rect.boundary[5] = Area->T;
324
ret = RTreeDeleteRect(&rect, area, &(Plus->Area_spidx));
532
Line = Plus->Line[abs(Area->lines[0])];
533
topo = (struct P_topo_b *)Line->topo;
534
Node = Plus->Node[topo->N1];
536
rect.boundary[0] = Node->x;
537
rect.boundary[1] = Node->y;
538
rect.boundary[2] = Node->z;
539
rect.boundary[3] = Node->x;
540
rect.boundary[4] = Node->y;
541
rect.boundary[5] = Node->z;
543
ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
327
546
G_fatal_error(_("Unable to delete area %d from spatial index"), area);
342
561
int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
567
struct P_topo_b *topo;
568
static struct RTree_Rect rect;
569
static int rect_init = 0;
572
/* always 6 sides for 3D */
573
rect.boundary = G_malloc(6 * sizeof(RectReal));
348
577
G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
350
579
Isle = Plus->Isle[isle];
352
rect.boundary[0] = Isle->W;
353
rect.boundary[1] = Isle->S;
354
rect.boundary[2] = Isle->B;
355
rect.boundary[3] = Isle->E;
356
rect.boundary[4] = Isle->N;
357
rect.boundary[5] = Isle->T;
359
ret = RTreeDeleteRect(&rect, isle, &(Plus->Isle_spidx));
581
Line = Plus->Line[abs(Isle->lines[0])];
582
topo = (struct P_topo_b *)Line->topo;
583
Node = Plus->Node[topo->N1];
585
rect.boundary[0] = Node->x;
586
rect.boundary[1] = Node->y;
587
rect.boundary[2] = Node->z;
588
rect.boundary[3] = Node->x;
589
rect.boundary[4] = Node->y;
590
rect.boundary[5] = Node->z;
592
ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
362
595
G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
367
/* This function is called by RTreeSearch() to add selected node/line/area/isle to thelist */
368
static int _add_item(int id, struct ilist *list)
370
dig_list_add(list, id);
600
/* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
601
static int _add_item(int id, const struct RTree_Rect *rect,
604
G_ilist_add(list, id);
608
/* This function is called by RTreeSearch() to add
609
* selected node/line/area/isle to the box list */
610
static int _add_item_with_box(int id, const struct RTree_Rect *rect,
611
struct boxlist *list)
613
struct bound_box box;
615
box.W = rect->boundary[0];
616
box.S = rect->boundary[1];
617
box.B = rect->boundary[2];
618
box.E = rect->boundary[3];
619
box.N = rect->boundary[4];
620
box.T = rect->boundary[5];
622
dig_boxlist_add(list, id, &box);
629
struct bound_box *box;
632
/* This function is called by RTreeSearch() to add
633
* selected node/line/area/isle to the box list */
634
static int _set_item_box(int id, const struct RTree_Rect *rect,
635
struct boxid *box_id)
637
if (id == box_id->id) {
639
box_id->box->W = rect->boundary[0];
640
box_id->box->S = rect->boundary[1];
641
box_id->box->B = rect->boundary[2];
642
box_id->box->E = rect->boundary[3];
643
box_id->box->N = rect->boundary[4];
644
box_id->box->T = rect->boundary[5];
435
729
rect.boundary[5] = z;
438
RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
733
RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
735
rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
444
\brief Select lines by box
741
\brief Select lines with boxes by box
446
743
\param Plus pointer to Plus_head structure
447
744
\param box bounding box
448
\param list list of selected lines
745
\param list boxlist of selected lines
450
747
\return number of selected lines
453
dig_select_lines(struct Plus_head *Plus, BOUND_BOX * box, struct ilist *list)
750
int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
751
struct boxlist *list)
457
G_debug(3, "dig_select_lines()");
753
static struct RTree_Rect rect;
754
static int rect_init = 0;
757
/* always 6 sides for 3D */
758
rect.boundary = G_malloc(6 * sizeof(RectReal));
762
G_debug(3, "dig_select_lines_with_box()");
459
764
list->n_values = 0;
464
769
rect.boundary[3] = box->E;
465
770
rect.boundary[4] = box->N;
466
771
rect.boundary[5] = box->T;
467
RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item, list);
774
RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
776
rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
469
778
return (list->n_values);
782
\brief Find box for line
784
\param Plus pointer to Plus_head structure
786
\param[out] box bounding box
788
\return > 0 bounding box for line found
791
int dig_find_line_box(struct Plus_head *Plus, int line,
792
struct bound_box *box)
797
static struct RTree_Rect rect;
798
static int rect_init = 0;
800
G_debug(3, "dig_find_line_box()");
803
/* always 6 sides for 3D */
804
rect.boundary = G_malloc(6 * sizeof(RectReal));
808
Line = Plus->Line[line];
811
/* GV_LINES: retrieve box from spatial index */
812
if (type & GV_LINES) {
813
struct P_node *Node = NULL;
815
if (type == GV_LINE) {
816
struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
818
Node = Plus->Node[topo->N1];
820
else if (type == GV_BOUNDARY) {
821
struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
823
Node = Plus->Node[topo->N1];
826
rect.boundary[0] = Node->x;
827
rect.boundary[1] = Node->y;
828
rect.boundary[2] = Node->z;
829
rect.boundary[3] = Node->x;
830
rect.boundary[4] = Node->y;
831
rect.boundary[5] = Node->z;
837
ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id);
839
ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
844
/* do not translate this error because
845
* 1. this error is not supposed to happen
846
* 2. the maintainer at which this message is directed prefers english */
847
G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for lines and boundaries.");
473
\brief Select areas by box
853
\brief Select areas with boxes by box
475
855
\param Plus pointer to Plus_head structure
476
856
\param box bounding box
477
\param list list of selected lines
857
\param list boxlist of selected areas
479
859
\return number of selected areas
482
dig_select_areas(struct Plus_head *Plus, BOUND_BOX * box, struct ilist *list)
862
dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
863
struct boxlist *list)
486
G_debug(3, "dig_select_areas()");
865
static struct RTree_Rect rect;
866
static int rect_init = 0;
869
/* always 6 sides for 3D */
870
rect.boundary = G_malloc(6 * sizeof(RectReal));
874
G_debug(3, "dig_select_areas_with_box()");
488
876
list->n_values = 0;
493
881
rect.boundary[3] = box->E;
494
882
rect.boundary[4] = box->N;
495
883
rect.boundary[5] = box->T;
496
RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item, list);
886
RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
888
rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
498
890
return (list->n_values);
502
\brief Select isles by box
894
\brief Find bounding box for given area
896
\param Plus pointer to Plus_head structure
898
\param[out] box bounding box
900
\return > 0 bounding box for area found
903
int dig_find_area_box(struct Plus_head *Plus, int area,
904
struct bound_box *box)
911
struct P_topo_b *topo;
912
static struct RTree_Rect rect;
913
static int rect_init = 0;
915
G_debug(3, "dig_find_area_box()");
918
/* always 6 sides for 3D */
919
rect.boundary = G_malloc(6 * sizeof(RectReal));
923
Area = Plus->Area[area];
924
Line = Plus->Line[abs(Area->lines[0])];
925
topo = (struct P_topo_b *)Line->topo;
926
Node = Plus->Node[topo->N1];
928
rect.boundary[0] = Node->x;
929
rect.boundary[1] = Node->y;
930
rect.boundary[2] = Node->z;
931
rect.boundary[3] = Node->x;
932
rect.boundary[4] = Node->y;
933
rect.boundary[5] = Node->z;
939
ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id);
941
ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
947
\brief Select isles with boxes by box
504
949
\param Plus pointer to Plus_head structure
505
950
\param box bounding box
506
\param list list of selected lines
951
\param list boxlist of selected isles
508
953
\return number of selected isles
511
dig_select_isles(struct Plus_head *Plus, BOUND_BOX * box, struct ilist *list)
956
dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
957
struct boxlist *list)
515
G_debug(3, "dig_select_isles()");
959
static struct RTree_Rect rect;
960
static int rect_init = 0;
963
/* always 6 sides for 3D */
964
rect.boundary = G_malloc(6 * sizeof(RectReal));
968
G_debug(3, "dig_select_areas_with_box()");
517
970
list->n_values = 0;
522
975
rect.boundary[3] = box->E;
523
976
rect.boundary[4] = box->N;
524
977
rect.boundary[5] = box->T;
525
RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item, list);
980
RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list);
982
rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
527
984
return (list->n_values);
988
\brief Find box for isle
990
\param Plus pointer to Plus_head structure
992
\param[out] box bounding box
994
\return > 0 bounding box for isle found
997
int dig_find_isle_box(struct Plus_head *Plus, int isle,
998
struct bound_box *box)
1001
struct boxid box_id;
1002
struct P_isle *Isle;
1003
struct P_line *Line;
1004
struct P_node *Node;
1005
struct P_topo_b *topo;
1006
static struct RTree_Rect rect;
1007
static int rect_init = 0;
1009
G_debug(3, "dig_find_isle_box()");
1012
/* always 6 sides for 3D */
1013
rect.boundary = G_malloc(6 * sizeof(RectReal));
1017
Isle = Plus->Isle[isle];
1018
Line = Plus->Line[abs(Isle->lines[0])];
1019
topo = (struct P_topo_b *)Line->topo;
1020
Node = Plus->Node[topo->N1];
1022
rect.boundary[0] = Node->x;
1023
rect.boundary[1] = Node->y;
1024
rect.boundary[2] = Node->z;
1025
rect.boundary[3] = Node->x;
1026
rect.boundary[4] = Node->y;
1027
rect.boundary[5] = Node->z;
1032
if (Plus->Spidx_new)
1033
ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id);
1035
ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id, Plus);