@@ -19,9 +19,19 @@ pub fn generate_bezier_path(
1919 zoom : f32 ,
2020 min_offset : f32 ,
2121) -> String {
22+ // If distance is very small, use a straight line to avoid zig-zags
23+ let dx = end_x - start_x;
24+ let dy = end_y - start_y;
25+ let dist_sq = dx * dx + dy * dy;
26+ let threshold = 10.0 * zoom;
27+
28+ if dist_sq < threshold * threshold {
29+ return format ! ( "M {} {} L {} {}" , start_x, start_y, end_x, end_y) ;
30+ }
31+
2232 // Calculate control point offset (horizontal bezier)
23- let dx = ( end_x - start_x ) . abs ( ) ;
24- let offset = ( dx * 0.5 ) . max ( min_offset * zoom) ;
33+ let dx_abs = dx . abs ( ) ;
34+ let offset = ( dx_abs * 0.5 ) . max ( min_offset * zoom) ;
2535
2636 // Control points extend horizontally from start and end
2737 let ctrl1_x = start_x + offset;
@@ -72,9 +82,21 @@ pub fn generate_partial_bezier_path(
7282 return generate_bezier_path ( start_x, start_y, end_x, end_y, zoom, min_offset) ;
7383 }
7484
85+ // If distance is very small, use a straight line
86+ let dx_full = end_x - start_x;
87+ let dy_full = end_y - start_y;
88+ let dist_sq = dx_full * dx_full + dy_full * dy_full;
89+ let threshold = 10.0 * zoom;
90+
91+ if dist_sq < threshold * threshold {
92+ let curr_x = start_x + dx_full * t;
93+ let curr_y = start_y + dy_full * t;
94+ return format ! ( "M {} {} L {} {}" , start_x, start_y, curr_x, curr_y) ;
95+ }
96+
7597 // Calculate full bezier control points
76- let dx = ( end_x - start_x ) . abs ( ) ;
77- let offset = ( dx * 0.5 ) . max ( min_offset * zoom) ;
98+ let dx_abs = dx_full . abs ( ) ;
99+ let offset = ( dx_abs * 0.5 ) . max ( min_offset * zoom) ;
78100
79101 let p0 = ( start_x, start_y) ;
80102 let p1 = ( start_x + offset, start_y) ;
@@ -131,8 +153,22 @@ impl CubicBezier {
131153 zoom : f32 ,
132154 min_offset : f32 ,
133155 ) -> Self {
134- let dx = ( end_x - start_x) . abs ( ) ;
135- let offset = ( dx * 0.5 ) . max ( min_offset * zoom) ;
156+ let dx = end_x - start_x;
157+ let dy = end_y - start_y;
158+ let dist_sq = dx * dx + dy * dy;
159+ let threshold = 10.0 * zoom;
160+
161+ if dist_sq < threshold * threshold {
162+ return CubicBezier {
163+ p0 : ( start_x, start_y) ,
164+ p1 : ( start_x, start_y) ,
165+ p2 : ( end_x, end_y) ,
166+ p3 : ( end_x, end_y) ,
167+ } ;
168+ }
169+
170+ let dx_abs = dx. abs ( ) ;
171+ let offset = ( dx_abs * 0.5 ) . max ( min_offset * zoom) ;
136172
137173 CubicBezier {
138174 p0 : ( start_x, start_y) ,
@@ -239,12 +275,26 @@ mod tests {
239275 assert ! ( path. ends_with( "100 80" ) ) ;
240276 }
241277
278+ #[ test]
279+ fn test_bezier_path_small_distance ( ) {
280+ // Distance is 5.0, threshold is 10.0
281+ let path = generate_bezier_path ( 0.0 , 0.0 , 5.0 , 0.0 , 1.0 , 50.0 ) ;
282+ assert ! ( path. contains( " L " ) ) ;
283+ assert ! ( !path. contains( " C " ) ) ;
284+
285+ // Distance is 15.0, threshold is 10.0
286+ let path2 = generate_bezier_path ( 0.0 , 0.0 , 15.0 , 0.0 , 1.0 , 50.0 ) ;
287+ assert ! ( path2. contains( " C " ) ) ;
288+ assert ! ( !path2. contains( " L " ) ) ;
289+ }
290+
242291 #[ test]
243292 fn test_bezier_path_zero_distance ( ) {
244- // Start and end at same point - should still produce valid path
293+ // Start and end at same point - should produce a straight line (effectively a point)
245294 let path = generate_bezier_path ( 50.0 , 50.0 , 50.0 , 50.0 , 1.0 , 50.0 ) ;
246295 assert ! ( path. starts_with( "M " ) ) ;
247- assert ! ( path. contains( " C " ) ) ;
296+ assert ! ( path. contains( " L " ) ) ;
297+ assert ! ( !path. contains( " C " ) ) ;
248298 }
249299
250300 #[ test]
0 commit comments