use super::line::{CurveType, LineGenerator};
pub struct AreaGenerator {
curve: CurveType,
}
impl AreaGenerator {
pub fn new() -> Self {
Self {
curve: CurveType::Linear,
}
}
pub fn curve(mut self, curve: CurveType) -> Self {
self.curve = curve;
self
}
pub fn generate_line(&self, points: &[(f64, f64, f64)]) -> String {
if points.is_empty() {
return String::new();
}
let top_points: Vec<(f64, f64)> = points.iter().map(|&(x, _y0, y1)| (x, y1)).collect();
let line_gen = LineGenerator::new().curve(self.curve);
line_gen.generate(&top_points)
}
pub fn generate(&self, points: &[(f64, f64, f64)]) -> String {
if points.is_empty() {
return String::new();
}
let top_points: Vec<(f64, f64)> = points.iter().map(|&(x, _y0, y1)| (x, y1)).collect();
let bottom_points: Vec<(f64, f64)> = points.iter().rev().map(|&(x, y0, _y1)| (x, y0)).collect();
let line_gen = LineGenerator::new().curve(self.curve);
let top_path = line_gen.generate(&top_points);
let bottom_path = line_gen.generate(&bottom_points);
let bottom_continuation = if bottom_path.len() > 1 {
format!("L{}", &bottom_path[1..])
} else {
String::new()
};
format!("{}{}Z", top_path, bottom_continuation)
}
}
impl Default for AreaGenerator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn area_basic() {
let gen = AreaGenerator::new();
let path = gen.generate(&[
(0.0, 100.0, 10.0),
(50.0, 100.0, 20.0),
(100.0, 100.0, 5.0),
]);
assert!(path.starts_with("M"), "Path should start with M, got: {}", path);
assert!(path.contains("L"), "Path should contain L commands, got: {}", path);
assert!(path.ends_with("Z"), "Path should end with Z, got: {}", path);
}
#[test]
fn area_empty() {
let gen = AreaGenerator::new();
let path = gen.generate(&[]);
assert_eq!(path, "");
}
}