11use crate :: utils:: direction:: Direction ;
22use crate :: utils:: point:: Point ;
33use crate :: utils:: range:: Range ;
4+ use crate :: utils:: traits:: Intersect ;
45
56/// Represents a line on a grid that can only be horizontal or vertical
67#[ derive( Debug , Copy , Clone , PartialEq ) ]
@@ -90,6 +91,7 @@ impl GridLine {
9091 }
9192
9293 /// It extends its size by 1 in the direction of orientation
94+ #[ allow( dead_code) ]
9395 pub fn extend ( & self ) -> Self {
9496 match self {
9597 GridLine :: Horizontal {
@@ -118,6 +120,7 @@ impl GridLine {
118120 }
119121
120122 /// Move line in direction by 1
123+ #[ allow( dead_code) ]
121124 pub fn moved ( & self , direction : Direction ) -> Self {
122125 let start = self . start ( ) ;
123126 let end = self . end ( ) ;
@@ -131,16 +134,64 @@ impl GridLine {
131134 }
132135 }
133136
137+ #[ allow( dead_code) ]
134138 pub fn direction ( & self ) -> Direction {
135139 self . start ( ) . direction ( & self . end ( ) )
136140 }
137141}
138142
143+ impl Intersect < GridLine > for GridLine {
144+ fn intersect ( & self , value : & GridLine ) -> bool {
145+ match ( self , value) {
146+ // Two horizontal lines intersect if they're on the same y and their x ranges overlap
147+ (
148+ Self :: Horizontal { y, x_start, x_end } ,
149+ Self :: Horizontal {
150+ y : y2,
151+ x_start : x_start2,
152+ x_end : x_end2,
153+ } ,
154+ ) => {
155+ if y != y2 {
156+ return false ;
157+ }
158+ let my_x = Range :: from_unordered ( * x_start, * x_end) ;
159+ let other_x = Range :: from_unordered ( * x_start2, * x_end2) ;
160+ my_x. collide ( & other_x)
161+ }
162+ // Two vertical lines intersect if they're on the same x and their y ranges overlap
163+ (
164+ Self :: Vertical { x, y_start, y_end } ,
165+ Self :: Vertical {
166+ x : x2,
167+ y_start : y_start2,
168+ y_end : y_end2,
169+ } ,
170+ ) => {
171+ if x != x2 {
172+ return false ;
173+ }
174+ let my_y = Range :: from_unordered ( * y_start, * y_end) ;
175+ let other_y = Range :: from_unordered ( * y_start2, * y_end2) ;
176+ my_y. collide ( & other_y)
177+ }
178+ // Horizontal and vertical lines intersect if they cross
179+ ( Self :: Horizontal { y, x_start, x_end } , Self :: Vertical { x, y_start, y_end } )
180+ | ( Self :: Vertical { x, y_start, y_end } , Self :: Horizontal { y, x_start, x_end } ) => {
181+ let x_range = Range :: from_unordered ( * x_start, * x_end) ;
182+ let y_range = Range :: from_unordered ( * y_start, * y_end) ;
183+ x_range. contains ( * x) && y_range. contains ( * y)
184+ }
185+ }
186+ }
187+ }
188+
139189#[ cfg( test) ]
140190mod tests {
141191 use crate :: utils:: direction:: Direction ;
142192 use crate :: utils:: grid_line:: GridLine ;
143193 use crate :: utils:: point:: Point ;
194+ use crate :: utils:: traits:: Intersect ;
144195
145196 #[ test]
146197 fn new_horizontal ( ) {
@@ -325,4 +376,174 @@ mod tests {
325376 let line = GridLine :: new ( Point :: new ( 2 , 4 ) , Point :: new ( 2 , 1 ) ) . unwrap ( ) ;
326377 assert_eq ! ( Direction :: North , line. direction( ) ) ;
327378 }
379+
380+ #[ test]
381+ fn intersect_two_horizontal ( ) {
382+ let line = GridLine :: new ( Point :: new ( 2 , 3 ) , Point :: new ( 5 , 3 ) ) . unwrap ( ) ;
383+
384+ //above
385+ let other = GridLine :: new ( Point :: new ( 2 , 4 ) , Point :: new ( 5 , 4 ) ) . unwrap ( ) ;
386+ assert ! ( !line. intersect( & other) ) ;
387+ assert ! ( !other. intersect( & line) ) ;
388+
389+ //below
390+ let other = GridLine :: new ( Point :: new ( 2 , 5 ) , Point :: new ( 5 , 5 ) ) . unwrap ( ) ;
391+ assert ! ( !line. intersect( & other) ) ;
392+ assert ! ( !other. intersect( & line) ) ;
393+
394+ //same y, before
395+ let other = GridLine :: new ( Point :: new ( 0 , 3 ) , Point :: new ( 1 , 3 ) ) . unwrap ( ) ;
396+ assert ! ( !line. intersect( & other) ) ;
397+ assert ! ( !other. intersect( & line) ) ;
398+
399+ //same y, intersect before
400+ let other = GridLine :: new ( Point :: new ( 0 , 3 ) , Point :: new ( 2 , 3 ) ) . unwrap ( ) ;
401+ assert ! ( line. intersect( & other) ) ;
402+ assert ! ( other. intersect( & line) ) ;
403+
404+ //same y, inside
405+ let other = GridLine :: new ( Point :: new ( 3 , 3 ) , Point :: new ( 4 , 3 ) ) . unwrap ( ) ;
406+ assert ! ( line. intersect( & other) ) ;
407+ assert ! ( other. intersect( & line) ) ;
408+
409+ // //same y, intersect after
410+ let other = GridLine :: new ( Point :: new ( 5 , 3 ) , Point :: new ( 9 , 3 ) ) . unwrap ( ) ;
411+ assert ! ( line. intersect( & other) ) ;
412+ assert ! ( other. intersect( & line) ) ;
413+
414+ // //same y, after
415+ let other = GridLine :: new ( Point :: new ( 6 , 3 ) , Point :: new ( 10 , 3 ) ) . unwrap ( ) ;
416+ assert ! ( !line. intersect( & other) ) ;
417+ assert ! ( !other. intersect( & line) ) ;
418+ }
419+
420+ #[ test]
421+ fn intersect_two_vertical ( ) {
422+ let line = GridLine :: new ( Point :: new ( 3 , 2 ) , Point :: new ( 3 , 5 ) ) . unwrap ( ) ;
423+
424+ // Different x, to the left
425+ let other = GridLine :: new ( Point :: new ( 2 , 2 ) , Point :: new ( 2 , 5 ) ) . unwrap ( ) ;
426+ assert ! ( !line. intersect( & other) ) ;
427+ assert ! ( !other. intersect( & line) ) ;
428+
429+ // Different x, to the right
430+ let other = GridLine :: new ( Point :: new ( 4 , 2 ) , Point :: new ( 4 , 5 ) ) . unwrap ( ) ;
431+ assert ! ( !line. intersect( & other) ) ;
432+ assert ! ( !other. intersect( & line) ) ;
433+
434+ // Same x, above
435+ let other = GridLine :: new ( Point :: new ( 3 , 0 ) , Point :: new ( 3 , 1 ) ) . unwrap ( ) ;
436+ assert ! ( !line. intersect( & other) ) ;
437+ assert ! ( !other. intersect( & line) ) ;
438+
439+ // Same x, intersect above
440+ let other = GridLine :: new ( Point :: new ( 3 , 0 ) , Point :: new ( 3 , 2 ) ) . unwrap ( ) ;
441+ assert ! ( line. intersect( & other) ) ;
442+ assert ! ( other. intersect( & line) ) ;
443+
444+ // Same x, inside
445+ let other = GridLine :: new ( Point :: new ( 3 , 3 ) , Point :: new ( 3 , 4 ) ) . unwrap ( ) ;
446+ assert ! ( line. intersect( & other) ) ;
447+ assert ! ( other. intersect( & line) ) ;
448+
449+ // Same x, intersect below
450+ let other = GridLine :: new ( Point :: new ( 3 , 5 ) , Point :: new ( 3 , 9 ) ) . unwrap ( ) ;
451+ assert ! ( line. intersect( & other) ) ;
452+ assert ! ( other. intersect( & line) ) ;
453+
454+ // Same x, below
455+ let other = GridLine :: new ( Point :: new ( 3 , 6 ) , Point :: new ( 3 , 10 ) ) . unwrap ( ) ;
456+ assert ! ( !line. intersect( & other) ) ;
457+ assert ! ( !other. intersect( & line) ) ;
458+
459+ // Same x, completely overlapping
460+ let other = GridLine :: new ( Point :: new ( 3 , 1 ) , Point :: new ( 3 , 6 ) ) . unwrap ( ) ;
461+ assert ! ( line. intersect( & other) ) ;
462+ assert ! ( other. intersect( & line) ) ;
463+ }
464+
465+ #[ test]
466+ fn intersect_horizontal_vertical ( ) {
467+ let horizontal = GridLine :: new ( Point :: new ( 2 , 3 ) , Point :: new ( 6 , 3 ) ) . unwrap ( ) ;
468+
469+ // Vertical line crosses through horizontal
470+ let vertical = GridLine :: new ( Point :: new ( 4 , 1 ) , Point :: new ( 4 , 5 ) ) . unwrap ( ) ;
471+ assert ! ( horizontal. intersect( & vertical) ) ;
472+ assert ! ( vertical. intersect( & horizontal) ) ;
473+
474+ // Vertical line at start of horizontal
475+ let vertical = GridLine :: new ( Point :: new ( 2 , 1 ) , Point :: new ( 2 , 5 ) ) . unwrap ( ) ;
476+ assert ! ( horizontal. intersect( & vertical) ) ;
477+ assert ! ( vertical. intersect( & horizontal) ) ;
478+
479+ // Vertical line at end of horizontal
480+ let vertical = GridLine :: new ( Point :: new ( 6 , 1 ) , Point :: new ( 6 , 5 ) ) . unwrap ( ) ;
481+ assert ! ( horizontal. intersect( & vertical) ) ;
482+ assert ! ( vertical. intersect( & horizontal) ) ;
483+
484+ // Vertical line before horizontal (x too small)
485+ let vertical = GridLine :: new ( Point :: new ( 1 , 1 ) , Point :: new ( 1 , 5 ) ) . unwrap ( ) ;
486+ assert ! ( !horizontal. intersect( & vertical) ) ;
487+ assert ! ( !vertical. intersect( & horizontal) ) ;
488+
489+ // Vertical line after horizontal (x too large)
490+ let vertical = GridLine :: new ( Point :: new ( 7 , 1 ) , Point :: new ( 7 , 5 ) ) . unwrap ( ) ;
491+ assert ! ( !horizontal. intersect( & vertical) ) ;
492+ assert ! ( !vertical. intersect( & horizontal) ) ;
493+
494+ // Vertical line above horizontal (y too small)
495+ let vertical = GridLine :: new ( Point :: new ( 4 , 0 ) , Point :: new ( 4 , 2 ) ) . unwrap ( ) ;
496+ assert ! ( !horizontal. intersect( & vertical) ) ;
497+ assert ! ( !vertical. intersect( & horizontal) ) ;
498+
499+ // Vertical line below horizontal (y too large)
500+ let vertical = GridLine :: new ( Point :: new ( 4 , 4 ) , Point :: new ( 4 , 6 ) ) . unwrap ( ) ;
501+ assert ! ( !horizontal. intersect( & vertical) ) ;
502+ assert ! ( !vertical. intersect( & horizontal) ) ;
503+
504+ // Vertical line touches horizontal at endpoint
505+ let vertical = GridLine :: new ( Point :: new ( 4 , 3 ) , Point :: new ( 4 , 6 ) ) . unwrap ( ) ;
506+ assert ! ( horizontal. intersect( & vertical) ) ;
507+ assert ! ( vertical. intersect( & horizontal) ) ;
508+ }
509+
510+ #[ test]
511+ fn intersect_vertical_horizontal ( ) {
512+ let vertical = GridLine :: new ( Point :: new ( 4 , 2 ) , Point :: new ( 4 , 6 ) ) . unwrap ( ) ;
513+
514+ // Horizontal line crosses through vertical
515+ let horizontal = GridLine :: new ( Point :: new ( 1 , 4 ) , Point :: new ( 7 , 4 ) ) . unwrap ( ) ;
516+ assert ! ( vertical. intersect( & horizontal) ) ;
517+ assert ! ( horizontal. intersect( & vertical) ) ;
518+
519+ // Horizontal line at start of vertical
520+ let horizontal = GridLine :: new ( Point :: new ( 1 , 2 ) , Point :: new ( 7 , 2 ) ) . unwrap ( ) ;
521+ assert ! ( vertical. intersect( & horizontal) ) ;
522+ assert ! ( horizontal. intersect( & vertical) ) ;
523+
524+ // Horizontal line at end of vertical
525+ let horizontal = GridLine :: new ( Point :: new ( 1 , 6 ) , Point :: new ( 7 , 6 ) ) . unwrap ( ) ;
526+ assert ! ( vertical. intersect( & horizontal) ) ;
527+ assert ! ( horizontal. intersect( & vertical) ) ;
528+
529+ // Horizontal line above vertical (y too small)
530+ let horizontal = GridLine :: new ( Point :: new ( 1 , 1 ) , Point :: new ( 7 , 1 ) ) . unwrap ( ) ;
531+ assert ! ( !vertical. intersect( & horizontal) ) ;
532+ assert ! ( !horizontal. intersect( & vertical) ) ;
533+
534+ // Horizontal line below vertical (y too large)
535+ let horizontal = GridLine :: new ( Point :: new ( 1 , 7 ) , Point :: new ( 7 , 7 ) ) . unwrap ( ) ;
536+ assert ! ( !vertical. intersect( & horizontal) ) ;
537+ assert ! ( !horizontal. intersect( & vertical) ) ;
538+
539+ // Horizontal line to the left of vertical (x too small)
540+ let horizontal = GridLine :: new ( Point :: new ( 1 , 4 ) , Point :: new ( 3 , 4 ) ) . unwrap ( ) ;
541+ assert ! ( !vertical. intersect( & horizontal) ) ;
542+ assert ! ( !horizontal. intersect( & vertical) ) ;
543+
544+ // Horizontal line to the right of vertical (x too large)
545+ let horizontal = GridLine :: new ( Point :: new ( 5 , 4 ) , Point :: new ( 7 , 4 ) ) . unwrap ( ) ;
546+ assert ! ( !vertical. intersect( & horizontal) ) ;
547+ assert ! ( !horizontal. intersect( & vertical) ) ;
548+ }
328549}
0 commit comments