1+ use line_clipping:: { cohen_sutherland, LineSegment , Point , Window } ;
12use ratatui_core:: style:: Color ;
23
34use crate :: canvas:: { Painter , Shape } ;
@@ -31,13 +32,21 @@ impl Line {
3132}
3233
3334impl Shape for Line {
35+ #[ allow( clippy:: similar_names) ]
3436 fn draw ( & self , painter : & mut Painter ) {
35- let Some ( ( x1, y1) ) = painter. get_point ( self . x1 , self . y1 ) else {
37+ let ( x_bounds, y_bounds) = painter. bounds ( ) ;
38+ let Some ( ( world_x1, world_y1, world_x2, world_y2) ) =
39+ clip_line ( x_bounds, y_bounds, self . x1 , self . y1 , self . x2 , self . y2 )
40+ else {
3641 return ;
3742 } ;
38- let Some ( ( x2 , y2 ) ) = painter. get_point ( self . x2 , self . y2 ) else {
43+ let Some ( ( x1 , y1 ) ) = painter. get_point ( world_x1 , world_y1 ) else {
3944 return ;
4045 } ;
46+ let Some ( ( x2, y2) ) = painter. get_point ( world_x2, world_y2) else {
47+ return ;
48+ } ;
49+
4150 let ( dx, x_range) = if x2 >= x1 {
4251 ( x2 - x1, x1..=x2)
4352 } else {
@@ -71,6 +80,27 @@ impl Shape for Line {
7180 }
7281}
7382
83+ fn clip_line (
84+ & [ xmin, xmax] : & [ f64 ; 2 ] ,
85+ & [ ymin, ymax] : & [ f64 ; 2 ] ,
86+ x1 : f64 ,
87+ y1 : f64 ,
88+ x2 : f64 ,
89+ y2 : f64 ,
90+ ) -> Option < ( f64 , f64 , f64 , f64 ) > {
91+ if let Some ( LineSegment {
92+ p1 : Point { x : x1, y : y1 } ,
93+ p2 : Point { x : x2, y : y2 } ,
94+ } ) = cohen_sutherland:: clip_line (
95+ LineSegment :: new ( Point :: new ( x1, y1) , Point :: new ( x2, y2) ) ,
96+ Window :: new ( xmin, xmax, ymin, ymax) ,
97+ ) {
98+ Some ( ( x1, y1, x2, y2) )
99+ } else {
100+ None
101+ }
102+ }
103+
74104fn draw_line_low ( painter : & mut Painter , x1 : usize , y1 : usize , x2 : usize , y2 : usize , color : Color ) {
75105 let dx = ( x2 - x1) as isize ;
76106 let dy = ( y2 as isize - y1 as isize ) . abs ( ) ;
@@ -124,9 +154,59 @@ mod tests {
124154 use crate :: canvas:: Canvas ;
125155
126156 #[ rstest]
127- #[ case:: off_grid( & Line :: new( -1.0 , -1.0 , 10.0 , 10.0 , Color :: Red ) , [ " " ; 10 ] ) ]
128- #[ case:: off_grid( & Line :: new( 0.0 , 0.0 , 11.0 , 11.0 , Color :: Red ) , [ " " ; 10 ] ) ]
129- #[ case:: horizontal( & Line :: new( 0.0 , 0.0 , 10.0 , 0.0 , Color :: Red ) , [
157+ #[ case:: off_grid1( & Line :: new( -1.0 , 0.0 , -1.0 , 10.0 , Color :: Red ) , [ " " ; 10 ] ) ]
158+ #[ case:: off_grid2( & Line :: new( 0.0 , -1.0 , 10.0 , -1.0 , Color :: Red ) , [ " " ; 10 ] ) ]
159+ #[ case:: off_grid3( & Line :: new( -10.0 , 5.0 , -1.0 , 5.0 , Color :: Red ) , [ " " ; 10 ] ) ]
160+ #[ case:: off_grid4( & Line :: new( 5.0 , 11.0 , 5.0 , 20.0 , Color :: Red ) , [ " " ; 10 ] ) ]
161+ #[ case:: off_grid5( & Line :: new( -10.0 , 0.0 , 5.0 , 0.0 , Color :: Red ) , [
162+ " " ,
163+ " " ,
164+ " " ,
165+ " " ,
166+ " " ,
167+ " " ,
168+ " " ,
169+ " " ,
170+ " " ,
171+ "••••• " ,
172+ ] ) ]
173+ #[ case:: off_grid6( & Line :: new( -1.0 , -1.0 , 10.0 , 10.0 , Color :: Red ) , [
174+ " •" ,
175+ " • " ,
176+ " • " ,
177+ " • " ,
178+ " • " ,
179+ " • " ,
180+ " • " ,
181+ " • " ,
182+ " • " ,
183+ "• " ,
184+ ] ) ]
185+ #[ case:: off_grid7( & Line :: new( 0.0 , 0.0 , 11.0 , 11.0 , Color :: Red ) , [
186+ " •" ,
187+ " • " ,
188+ " • " ,
189+ " • " ,
190+ " • " ,
191+ " • " ,
192+ " • " ,
193+ " • " ,
194+ " • " ,
195+ "• " ,
196+ ] ) ]
197+ #[ case:: off_grid8( & Line :: new( -1.0 , -1.0 , 11.0 , 11.0 , Color :: Red ) , [
198+ " •" ,
199+ " • " ,
200+ " • " ,
201+ " • " ,
202+ " • " ,
203+ " • " ,
204+ " • " ,
205+ " • " ,
206+ " • " ,
207+ "• " ,
208+ ] ) ]
209+ #[ case:: horizontal1( & Line :: new( 0.0 , 0.0 , 10.0 , 0.0 , Color :: Red ) , [
130210 " " ,
131211 " " ,
132212 " " ,
@@ -138,7 +218,7 @@ mod tests {
138218 " " ,
139219 "••••••••••" ,
140220 ] ) ]
141- #[ case:: horizontal ( & Line :: new( 10.0 , 10.0 , 0.0 , 10.0 , Color :: Red ) , [
221+ #[ case:: horizontal2 ( & Line :: new( 10.0 , 10.0 , 0.0 , 10.0 , Color :: Red ) , [
142222 "••••••••••" ,
143223 " " ,
144224 " " ,
@@ -150,10 +230,10 @@ mod tests {
150230 " " ,
151231 " " ,
152232 ] ) ]
153- #[ case:: vertical ( & Line :: new( 0.0 , 0.0 , 0.0 , 10.0 , Color :: Red ) , [ "• " ; 10 ] ) ]
154- #[ case:: vertical ( & Line :: new( 10.0 , 10.0 , 10.0 , 0.0 , Color :: Red ) , [ " •" ; 10 ] ) ]
233+ #[ case:: vertical1 ( & Line :: new( 0.0 , 0.0 , 0.0 , 10.0 , Color :: Red ) , [ "• " ; 10 ] ) ]
234+ #[ case:: vertical2 ( & Line :: new( 10.0 , 10.0 , 10.0 , 0.0 , Color :: Red ) , [ " •" ; 10 ] ) ]
155235 // dy < dx, x1 < x2
156- #[ case:: diagonal ( & Line :: new( 0.0 , 0.0 , 10.0 , 5.0 , Color :: Red ) , [
236+ #[ case:: diagonal1 ( & Line :: new( 0.0 , 0.0 , 10.0 , 5.0 , Color :: Red ) , [
157237 " " ,
158238 " " ,
159239 " " ,
@@ -166,7 +246,7 @@ mod tests {
166246 "• " ,
167247 ] ) ]
168248 // dy < dx, x1 > x2
169- #[ case:: diagonal ( & Line :: new( 10.0 , 0.0 , 0.0 , 5.0 , Color :: Red ) , [
249+ #[ case:: diagonal2 ( & Line :: new( 10.0 , 0.0 , 0.0 , 5.0 , Color :: Red ) , [
170250 " " ,
171251 " " ,
172252 " " ,
@@ -179,7 +259,7 @@ mod tests {
179259 " •" ,
180260 ] ) ]
181261 // dy > dx, y1 < y2
182- #[ case:: diagonal ( & Line :: new( 0.0 , 0.0 , 5.0 , 10.0 , Color :: Red ) , [
262+ #[ case:: diagonal3 ( & Line :: new( 0.0 , 0.0 , 5.0 , 10.0 , Color :: Red ) , [
183263 " • " ,
184264 " • " ,
185265 " • " ,
@@ -192,7 +272,7 @@ mod tests {
192272 "• " ,
193273 ] ) ]
194274 // dy > dx, y1 > y2
195- #[ case:: diagonal ( & Line :: new( 0.0 , 10.0 , 5.0 , 0.0 , Color :: Red ) , [
275+ #[ case:: diagonal4 ( & Line :: new( 0.0 , 10.0 , 5.0 , 0.0 , Color :: Red ) , [
196276 "• " ,
197277 "• " ,
198278 " • " ,
0 commit comments