#[cfg(test)]
mod tests {
use crate::contour::{Contour, ContourFunction, f_of_contour, fourier_decomposition};
use crate::model::EmbedOptions;
use crate::svg::{html_of_svg_path, svg_path_of_contour};
#[test]
fn test_square() {
let square = Contour {
points: vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)],
};
assert_eq!(square.points.len(), 4);
}
#[test]
fn test_f_of_contour_square() {
let square = Contour {
points: vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)],
};
let f = f_of_contour(&square);
assert_eq!(f.x(0.0), 0.0);
assert_eq!(f.y(0.0), 0.0);
assert_eq!(f.x(1.0 / 3.0), 1.0);
assert_eq!(f.y(1.0 / 3.0), 0.0);
assert_eq!(f.x(2.0 / 3.0), 1.0);
assert_eq!(f.y(2.0 / 3.0), 1.0);
assert_eq!(f.x(1.0), 0.0);
assert_eq!(f.y(1.0), 0.0);
assert_eq!(f.x(1.0 / 6.0), 0.5);
assert_eq!(f.y(1.0 / 6.0), 0.0);
assert_eq!(f.x(0.5), 1.0);
assert_eq!(f.y(0.5), 0.5);
assert_eq!(f.x(5.0 / 6.0), 0.5);
assert_eq!(f.y(5.0 / 6.0), 0.5);
}
#[test]
fn test_f_of_contour_vertical_line() {
let contour = Contour {
points: vec![(3.0, 0.0), (3.0, 5.0)],
};
let f = f_of_contour(&contour);
assert_eq!(f.x(0.0), f.x(1.0));
assert_eq!(f.y(0.0), 0.0);
assert_eq!(f.y(1.0), 5.0);
}
#[test]
fn test_with_offset() {
let contour = Contour {
points: vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)],
};
let f = f_of_contour(&contour).with_offset(10.0, 20.0);
assert_eq!(f.x(0.0), 10.0);
assert_eq!(f.y(0.0), 20.0);
assert_eq!(f.x(1.0 / 3.0), 11.0);
assert_eq!(f.y(1.0 / 3.0), 20.0);
assert_eq!(f.x(2.0 / 3.0), 11.0);
assert_eq!(f.y(2.0 / 3.0), 21.0);
}
#[test]
fn test_svg_path_of_contour_square() {
let square = Contour {
points: vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 0.0)],
};
let path = svg_path_of_contour(&square);
assert_eq!(path, "M 0 0 L 1 0 L 1 1 L 0 0");
}
#[test]
fn test_svg_path_of_contour_empty() {
let contour = Contour { points: vec![] };
let path = svg_path_of_contour(&contour);
assert_eq!(path, "");
}
#[test]
fn test_html_of_svg_path() {
let path = "M 0 0 L 1 0 L 1 1 L 0 0";
let opts = EmbedOptions::default();
let html = html_of_svg_path(path, &opts);
assert!(html.contains("<html>"));
assert!(html.contains("<svg"));
assert!(html.contains(&format!("d=\"{}\"", path)));
assert!(html.contains("</svg>"));
assert!(html.contains("</html>"));
}
#[test]
fn test_fourier_decomposition_circle() {
let n = 64;
let points: Vec<(f64, f64)> = (0..n)
.map(|i| {
let t = 2.0 * std::f64::consts::PI * i as f64 / n as f64;
(50.0 + 20.0 * t.cos(), 50.0 + 20.0 * t.sin())
})
.collect();
let contour = Contour { points };
let fd = fourier_decomposition(&contour, 4);
let eps = 1e-10;
let c0 = fd.coeffs.iter().find(|c| c.freq == 0).unwrap();
assert!((c0.re - 50.0).abs() < eps);
assert!((c0.im - 50.0).abs() < eps);
let c1 = fd.coeffs.iter().find(|c| c.freq == 1).unwrap();
assert!(
(c1.radius() - 20.0).abs() < eps,
"c1 radius: {}",
c1.radius()
);
for c in &fd.coeffs {
if c.freq != 0 && c.freq != 1 {
assert!(
c.radius() < eps,
"freq {} has radius {}",
c.freq,
c.radius()
);
}
}
for i in 0..n {
let t = i as f64 / n as f64;
let (rx, ry) = fd.eval(t);
let orig_t = 2.0 * std::f64::consts::PI * i as f64 / n as f64;
let ox = 50.0 + 20.0 * orig_t.cos();
let oy = 50.0 + 20.0 * orig_t.sin();
assert!(
(rx - ox).abs() < eps,
"x mismatch at i={}: {} vs {}",
i,
rx,
ox
);
assert!(
(ry - oy).abs() < eps,
"y mismatch at i={}: {} vs {}",
i,
ry,
oy
);
}
}
}