@@ -5,41 +5,71 @@ use crate::GeoFloat;
5
5
use std:: cell:: RefCell ;
6
6
use std:: rc:: Rc ;
7
7
8
+ use rstar:: RTree ;
9
+
8
10
pub ( crate ) struct RstarEdgeSetIntersector ;
9
11
10
12
impl RstarEdgeSetIntersector {
11
13
pub fn new ( ) -> Self {
12
14
RstarEdgeSetIntersector
13
15
}
16
+ }
14
17
15
- fn compute_intersects < F : GeoFloat > (
16
- & mut self ,
17
- edge0 : & Rc < RefCell < Edge < F > > > ,
18
- edge1 : & Rc < RefCell < Edge < F > > > ,
19
- segment_intersector : & mut SegmentIntersector < F > ,
20
- ) {
21
- let edge0_coords_len = edge0. borrow ( ) . coords ( ) . len ( ) - 1 ;
22
- let edge1_coords_len = edge1. borrow ( ) . coords ( ) . len ( ) - 1 ;
23
- for i0 in 0 ..edge0_coords_len {
24
- for i1 in 0 ..edge1_coords_len {
25
- segment_intersector. add_intersections ( edge0, i0, edge1, i1) ;
26
- }
18
+ struct Segment < ' a , F : GeoFloat + rstar:: RTreeNum > {
19
+ i : usize ,
20
+ edge : & ' a RefCell < Edge < F > > ,
21
+ envelope : rstar:: AABB < crate :: Coordinate < F > > ,
22
+ }
23
+
24
+ impl < ' a , F > Segment < ' a , F >
25
+ where
26
+ F : GeoFloat + rstar:: RTreeNum ,
27
+ {
28
+ fn new ( i : usize , edge : & ' a RefCell < Edge < F > > ) -> Self {
29
+ use crate :: rstar:: RTreeObject ;
30
+ let p1 = edge. borrow ( ) . coords ( ) [ i] ;
31
+ let p2 = edge. borrow ( ) . coords ( ) [ i + 1 ] ;
32
+ Self {
33
+ i,
34
+ edge,
35
+ envelope : rstar:: AABB :: from_corners ( p1, p2) ,
27
36
}
28
37
}
29
38
}
30
39
31
- impl < F : GeoFloat > EdgeSetIntersector < F > for RstarEdgeSetIntersector {
40
+ impl < ' a , F > rstar:: RTreeObject for Segment < ' a , F >
41
+ where
42
+ F : GeoFloat + rstar:: RTreeNum ,
43
+ {
44
+ type Envelope = rstar:: AABB < crate :: Coordinate < F > > ;
45
+
46
+ fn envelope ( & self ) -> Self :: Envelope {
47
+ self . envelope
48
+ }
49
+ }
50
+
51
+ impl < F > EdgeSetIntersector < F > for RstarEdgeSetIntersector
52
+ where
53
+ F : GeoFloat + rstar:: RTreeNum ,
54
+ {
32
55
fn compute_intersections_within_set (
33
56
& mut self ,
34
57
edges : & [ Rc < RefCell < Edge < F > > > ] ,
35
58
check_for_self_intersecting_edges : bool ,
36
59
segment_intersector : & mut SegmentIntersector < F > ,
37
60
) {
38
- for edge0 in edges. iter ( ) {
39
- for edge1 in edges. iter ( ) {
40
- if check_for_self_intersecting_edges || edge0. as_ptr ( ) != edge1. as_ptr ( ) {
41
- self . compute_intersects ( edge0, edge1, segment_intersector) ;
42
- }
61
+ let segments: Vec < Segment < F > > = edges
62
+ . iter ( )
63
+ . flat_map ( |edge| {
64
+ let start_of_final_segment: usize = RefCell :: borrow ( edge) . coords ( ) . len ( ) - 1 ;
65
+ ( 0 ..start_of_final_segment) . map ( |segment_i| Segment :: new ( segment_i, edge) )
66
+ } )
67
+ . collect ( ) ;
68
+ let tree = RTree :: bulk_load ( segments) ;
69
+
70
+ for ( edge0, edge1) in tree. intersection_candidates_with_other_tree ( & tree) {
71
+ if check_for_self_intersecting_edges || edge0. edge . as_ptr ( ) != edge1. edge . as_ptr ( ) {
72
+ segment_intersector. add_intersections ( edge0. edge , edge0. i , edge1. edge , edge1. i ) ;
43
73
}
44
74
}
45
75
}
@@ -50,10 +80,26 @@ impl<F: GeoFloat> EdgeSetIntersector<F> for RstarEdgeSetIntersector {
50
80
edges1 : & [ Rc < RefCell < Edge < F > > > ] ,
51
81
segment_intersector : & mut SegmentIntersector < F > ,
52
82
) {
53
- for edge0 in edges0 {
54
- for edge1 in edges1 {
55
- self . compute_intersects ( edge0, edge1, segment_intersector) ;
56
- }
83
+ let segments0: Vec < Segment < F > > = edges0
84
+ . iter ( )
85
+ . flat_map ( |edge| {
86
+ let start_of_final_segment: usize = RefCell :: borrow ( edge) . coords ( ) . len ( ) - 1 ;
87
+ ( 0 ..start_of_final_segment) . map ( |segment_i| Segment :: new ( segment_i, edge) )
88
+ } )
89
+ . collect ( ) ;
90
+ let tree_0 = RTree :: bulk_load ( segments0) ;
91
+
92
+ let segments1: Vec < Segment < F > > = edges1
93
+ . iter ( )
94
+ . flat_map ( |edge| {
95
+ let start_of_final_segment: usize = RefCell :: borrow ( edge) . coords ( ) . len ( ) - 1 ;
96
+ ( 0 ..start_of_final_segment) . map ( |segment_i| Segment :: new ( segment_i, edge) )
97
+ } )
98
+ . collect ( ) ;
99
+ let tree_1 = RTree :: bulk_load ( segments1) ;
100
+
101
+ for ( edge0, edge1) in tree_0. intersection_candidates_with_other_tree ( & tree_1) {
102
+ segment_intersector. add_intersections ( edge0. edge , edge0. i , edge1. edge , edge1. i ) ;
57
103
}
58
104
}
59
105
}
0 commit comments