1use crate::Element;
3use ::polygonical::point::Point;
4use ::polygonical::polygon::Polygon;
5
6pub struct Data {
8 segments: Vec<String>,
9}
10
11pub fn create(points: &[Point]) -> Element {
13 Data::from_points(points).to_path()
14}
15
16pub fn create_closed(points: &[Point]) -> Element {
18 Data::from_points(points).close().to_path()
19}
20
21pub fn create_polygon(poly: &Polygon) -> Element {
23 Data::from_points(&poly.points).close().to_path()
24}
25
26impl Data {
27 pub fn new() -> Self {
29 Data { segments: vec![] }
30 }
31
32 pub fn from_points(points: &[Point]) -> Self {
35 let mut data = Data::new();
36 if points.len() > 1 {
37 data.move_to(points[0]);
38 for p in points[1..].iter() {
39 data.line_to(*p);
40 }
41 }
42
43 data
44 }
45
46 pub fn move_to(&mut self, p: Point) -> &mut Data {
48 self.segments.push(format!("M{:.3} {:.3}", p.x, p.y));
49
50 self
51 }
52
53 pub fn line_to(&mut self, p: Point) -> &mut Data {
55 self.segments.push(format!("L{:.3} {:.3}", p.x, p.y));
56
57 self
58 }
59
60 pub fn arc_to<RX, RY, ROT>(
62 &mut self,
63 p: Point,
64 rx: RX,
65 ry: RY,
66 rotation: ROT,
67 large: bool,
68 sweep: bool,
69 ) -> &mut Data
70 where
71 RX: std::fmt::Display,
72 RY: std::fmt::Display,
73 ROT: std::fmt::Display,
74 {
75 let lv = match large {
76 true => 1,
77 false => 0,
78 };
79
80 let sv = match sweep {
81 true => 1,
82 false => 0,
83 };
84
85 self.segments.push(format!(
86 "A{} {} {:.3} {} {} {:.3} {:.3}",
87 rx, ry, rotation, lv, sv, p.x, p.y
88 ));
89
90 self
91 }
92
93 pub fn close(&mut self) -> &mut Data {
95 self.segments.push("z".to_string());
96 self
97 }
98
99 pub fn build(&self) -> String {
101 self.segments.join(" ")
102 }
103
104 pub fn to_path(&self) -> Element {
106 let mut el = Element::new("path");
107 el.set("fill", "none");
108 el.set("d", self.build());
109 el
110 }
111}
112
113impl Default for Data {
114 fn default() -> Self {
115 Self::new()
116 }
117}