39 lines
1.9 KiB
Rust
39 lines
1.9 KiB
Rust
//! Dashed and dotted strokes are evenly spaced along the whole line, in any direction.
|
|
|
|
use notescraft_whiteboard::{StrokeStyle, rough::dash};
|
|
|
|
fn length(piece: &[[f32; 2]]) -> f32 {
|
|
piece.windows(2).map(|pair| ((pair[1][0] - pair[0][0]).powi(2) + (pair[1][1] - pair[0][1]).powi(2)).sqrt()).sum()
|
|
}
|
|
|
|
#[test]
|
|
fn dashes_start_where_the_pattern_says_not_at_the_line_start() {
|
|
let pieces = dash(&[vec![[0.0, 0.0], [100.0, 0.0]]], StrokeStyle::Dashed);
|
|
assert_eq!(pieces.len(), 9);
|
|
for (index, piece) in pieces.iter().enumerate() {
|
|
let start = f32::from(u8::try_from(index).unwrap_or(0)) * 12.0;
|
|
assert!((piece[0][0] - start).abs() < 1e-3, "dash {index} starts at {} not {start}", piece[0][0]);
|
|
assert!(length(piece) <= 8.001, "dash {index} is {} long", length(piece));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn dots_are_short_and_spaced_in_every_direction() {
|
|
for (dx, dy) in [(80.0, 60.0), (-80.0, 60.0), (80.0, -60.0), (-80.0, -60.0), (0.0, 100.0), (-100.0, 0.0)] {
|
|
let pieces = dash(&[vec![[0.0, 0.0], [dx, dy]]], StrokeStyle::Dotted);
|
|
assert!(pieces.len() >= 20, "{dx},{dy}: {} dots", pieces.len());
|
|
assert!(pieces.iter().all(|piece| length(piece) <= 1.001), "{dx},{dy}: every dot is at most 1 long");
|
|
let gaps: Vec<f32> = pieces.windows(2).map(|pair| length(&[*pair[0].last().unwrap_or(&[0.0, 0.0]), pair[1][0]])).collect();
|
|
assert!(gaps.iter().all(|gap| (gap - 3.0).abs() < 0.05), "{dx},{dy}: uneven gaps {gaps:?}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn a_pattern_continues_around_a_corner() {
|
|
let pieces = dash(&[vec![[0.0, 0.0], [5.0, 0.0], [5.0, 15.0]]], StrokeStyle::Dashed);
|
|
let total: f32 = pieces.iter().map(|piece| length(piece)).sum();
|
|
// 20 units of line: 0..8 on, 8..12 off, 12..20 on.
|
|
assert!((total - 16.0).abs() < 0.1, "drawn length {total}");
|
|
assert!(pieces.first().is_some_and(|piece| piece.contains(&[5.0, 0.0])), "the first dash bends around the corner");
|
|
}
|