@@ -23,17 +23,53 @@ where
2323 T : GeoNum ,
2424{
2525 fn intersects ( & self , rhs : & Line < T > ) -> bool {
26- let lb = self . min ( ) ;
27- let rt = self . max ( ) ;
28- let lt = Coord :: from ( ( lb. x , rt. y ) ) ;
29- let rb = Coord :: from ( ( rt. x , lb. y ) ) ;
30- // If either rhs.{start,end} lies inside Rect, then true
31- self . intersects ( & rhs. start )
32- || self . intersects ( & rhs. end )
33- || Line :: new ( lt, rt) . intersects ( rhs)
34- || Line :: new ( rt, rb) . intersects ( rhs)
35- || Line :: new ( lb, rb) . intersects ( rhs)
36- || Line :: new ( lt, lb) . intersects ( rhs)
26+ // adds overhead to worst case
27+ // but short circuits if a terminal intersects the rectangle
28+
29+ // if self.intersects(&rhs.start)|| self.intersects(&rhs.end) {
30+ // return true;
31+ // }
32+
33+ if !self . intersects ( & rhs. bounding_rect ( ) ) {
34+ return false ;
35+ }
36+
37+ /*
38+ o3 o2
39+ | /
40+ | /
41+ o0--o1
42+ If `rhs` line extended to infinity crosses any of these three lines,
43+ and bounding boxes intersect,
44+ then `rhs` (Line) intersects `self` (Rect).
45+ */
46+
47+ let c0 = self . min ( ) ;
48+ let c1 = coord ! { x: self . max( ) . x, y: self . min( ) . y} ;
49+ let o0 = T :: Ker :: orient2d ( rhs. start , rhs. end , c0) ;
50+ let o1 = T :: Ker :: orient2d ( rhs. start , rhs. end , c1) ;
51+ if o0 != o1 {
52+ return true ;
53+ }
54+
55+ let c2 = self . max ( ) ;
56+ let o2 = T :: Ker :: orient2d ( rhs. start , rhs. end , c2) ;
57+ if o0 != o2 {
58+ return true ;
59+ }
60+
61+ let c3 = coord ! { x: self . min( ) . x, y: self . max( ) . y} ;
62+ let o3 = T :: Ker :: orient2d ( rhs. start , rhs. end , c3) ;
63+ if o0 != o3 {
64+ return true ;
65+ }
66+
67+ // At this point we know all the orientations are equal and that the bounding boxes overlap.
68+ // The only ways there could be an intersection is if
69+ // 1. `self` (Rect) has degenerated to a line, and `rhs` (Line) is on that line.
70+ // 2. `self` (Rect) has degenerated to a point, and lies on `rhs` (Line).
71+ // 3. `rhs` (Line) is degenerated to a point.
72+ o0 == Orientation :: Collinear
3773 }
3874}
3975
@@ -117,10 +153,52 @@ where
117153 }
118154}
119155
156+ #[ cfg( test) ]
157+ mod test_line {
158+ use super :: * ;
159+ use crate :: wkt;
160+
161+ #[ test]
162+ fn test_overlap_bbox_no_overlap ( ) {
163+ let rect = wkt ! { RECT ( 6 4 , 10 0 ) } ;
164+ let line = wkt ! { LINE ( 0 0 , 10 10 ) } ;
165+
166+ assert ! ( !rect. intersects( & line) ) ;
167+ }
168+
169+ #[ test]
170+ fn test_degen_line ( ) {
171+ let rect = wkt ! { RECT ( 0 0 , 10 10 ) } ;
172+ let line = wkt ! { LINE ( 0 0 , 0 0 ) } ;
173+
174+ assert ! ( rect. intersects( & line) ) ;
175+ }
176+
177+ #[ test]
178+ fn test_degen_rect ( ) {
179+ let rect_pt = wkt ! { RECT ( 0 0 , 0 10 ) } ;
180+ let rect_line1 = wkt ! { RECT ( 0 0 , 0 10 ) } ;
181+ let rect_line2 = wkt ! { RECT ( 0 0 , 10 0 ) } ;
182+ let line = wkt ! { LINE ( 0 0 , 10 0 ) } ;
183+
184+ assert ! ( rect_pt. intersects( & line) ) ;
185+ assert ! ( rect_line1. intersects( & line) ) ;
186+ assert ! ( rect_line2. intersects( & line) ) ;
187+ }
188+ }
189+
120190#[ cfg( test) ]
121191mod test_triangle {
122192 use super :: * ;
123193
194+ #[ test]
195+ fn test_rhs_degenerate_line ( ) {
196+ let s: Rect < f64 > = Rect :: new ( ( 0 , 0 ) , ( 0 , 0 ) ) . convert ( ) ;
197+ let l = Line :: new ( coord ! { x: 0.0 , y: 0.0 } , coord ! { x: 0.0 , y: 0.0 } ) ;
198+
199+ assert ! ( s. intersects( & l) ) ;
200+ }
201+
124202 #[ test]
125203 fn test_disjoint ( ) {
126204 let rect: Rect < f64 > = Rect :: new ( ( 0 , 0 ) , ( 10 , 10 ) ) . convert ( ) ;
0 commit comments