use crate::Element;
use ::polygonical::point::Point;
use ::polygonical::polygon::Polygon;
pub struct Data {
segments: Vec<String>,
}
pub fn create(points: &[Point]) -> Element {
Data::from_points(points).to_path()
}
pub fn create_closed(points: &[Point]) -> Element {
Data::from_points(points).close().to_path()
}
pub fn create_polygon(poly: &Polygon) -> Element {
Data::from_points(&poly.points).close().to_path()
}
impl Data {
pub fn new() -> Self {
Data { segments: vec![] }
}
pub fn from_points(points: &[Point]) -> Self {
let mut data = Data::new();
if points.len() > 1 {
data.move_to(points[0]);
for p in points[1..].iter() {
data.line_to(*p);
}
}
data
}
pub fn move_to(&mut self, p: Point) -> &mut Data {
self.segments.push(format!("M{:.3} {:.3}", p.x, p.y));
self
}
pub fn line_to(&mut self, p: Point) -> &mut Data {
self.segments.push(format!("L{:.3} {:.3}", p.x, p.y));
self
}
pub fn arc_to<RX, RY, ROT>(
&mut self,
p: Point,
rx: RX,
ry: RY,
rotation: ROT,
large: bool,
sweep: bool,
) -> &mut Data
where
RX: std::fmt::Display,
RY: std::fmt::Display,
ROT: std::fmt::Display,
{
let lv = match large {
true => 1,
false => 0,
};
let sv = match sweep {
true => 1,
false => 0,
};
self.segments.push(format!(
"A{} {} {:.3} {} {} {:.3} {:.3}",
rx, ry, rotation, lv, sv, p.x, p.y
));
self
}
pub fn close(&mut self) -> &mut Data {
self.segments.push("z".to_string());
self
}
pub fn build(&self) -> String {
self.segments.join(" ")
}
pub fn to_path(&self) -> Element {
let mut el = Element::new("path");
el.set("fill", "none");
el.set("d", self.build());
el
}
}
impl Default for Data {
fn default() -> Self {
Self::new()
}
}