murrelet_common/
polyline.rs1use glam::{vec2, Mat4, Vec2};
5use itertools::Itertools;
6
7use crate::{geometry::SpotOnCurve, transform::TransformVec2};
8
9#[derive(Debug, Clone)]
10pub struct Polyline {
11 v: Vec<Vec2>,
12}
13impl Polyline {
14 pub fn new(v: Vec<Vec2>) -> Self {
15 Self { v }
16 }
17
18 pub fn empty() -> Self {
19 Self { v: vec![] }
20 }
21
22 pub fn is_empty(&self) -> bool {
23 self.v.is_empty()
24 }
25
26 pub fn reverse(&mut self) {
27 self.v.reverse()
28 }
29
30 pub fn first(&self) -> Option<&Vec2> {
31 self.v.first()
32 }
33
34 pub fn last(&self) -> Option<&Vec2> {
35 self.v.last()
36 }
37
38 pub fn len(&self) -> usize {
39 self.v.len()
40 }
41
42 pub fn vertices(&self) -> &[Vec2] {
43 &self.v
44 }
45
46 pub fn apply_transform(self, transform: Mat4) -> Self {
47 let vs = self
48 .into_iter_vec2()
49 .map(|x| {
50 let p = transform.transform_vec2(x);
51 vec2(p.x, p.y)
52 })
53 .collect_vec();
54 Polyline::new(vs)
55 }
56
57 pub fn transform_with<T: TransformVec2>(&self, t: &T) -> Self {
58 t.transform_many_vec2(self)
59 }
60
61 pub fn add_pt_to_end(&mut self, pt: Vec2) {
62 self.v.push(pt)
63 }
64}
65
66pub trait IsPolyline {
69 fn into_iter_vec2<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = Vec2> + 'a>;
70 fn as_polyline(self) -> Polyline;
71 fn into_vec(self) -> Vec<Vec2>;
72 fn clone_to_vec(&self) -> Vec<Vec2>;
73}
74
75impl IsPolyline for Polyline {
76 fn into_iter_vec2<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = Vec2> + 'a> {
77 Box::new(self.v.iter().cloned())
78 }
79
80 fn as_polyline(self) -> Polyline {
81 self
82 }
83
84 fn into_vec(self) -> Vec<Vec2> {
85 self.v
86 }
87
88 fn clone_to_vec(&self) -> Vec<Vec2> {
89 self.v.clone()
90 }
91}
92
93impl IsPolyline for &[Vec2] {
94 fn into_iter_vec2<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = Vec2> + 'a> {
95 Box::new(self.iter().cloned())
96 }
97
98 fn as_polyline(self) -> Polyline {
99 Polyline { v: self.to_vec() }
100 }
101
102 fn into_vec(self) -> Vec<Vec2> {
103 self.to_vec()
104 }
105
106 fn clone_to_vec(&self) -> Vec<Vec2> {
107 self.to_vec()
108 }
109}
110
111impl IsPolyline for Vec<Vec2> {
112 fn into_iter_vec2<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = Vec2> + 'a> {
113 Box::new(self.iter().cloned())
114 }
115
116 fn as_polyline(self) -> Polyline {
117 Polyline { v: self }
118 }
119
120 fn into_vec(self) -> Vec<Vec2> {
121 self
122 }
123
124 fn clone_to_vec(&self) -> Vec<Vec2> {
125 self.clone()
126 }
127}
128
129#[derive(Debug, Clone)]
133pub struct AngledPolyline {
134 v: Vec<SpotOnCurve>,
135}
136
137impl AngledPolyline {
138 pub fn new(v: Vec<SpotOnCurve>) -> Self {
139 Self { v }
140 }
141
142 pub fn empty() -> Self {
143 Self { v: vec![] }
144 }
145
146 pub fn is_empty(&self) -> bool {
147 self.v.is_empty()
148 }
149
150 pub fn reverse(&mut self) {
151 self.v.reverse()
152 }
153
154 pub fn first(&self) -> Option<&SpotOnCurve> {
155 self.v.first()
156 }
157
158 pub fn last(&self) -> Option<&SpotOnCurve> {
159 self.v.last()
160 }
161
162 pub fn len(&self) -> usize {
163 self.v.len()
164 }
165
166 pub fn vertices(&self) -> &[SpotOnCurve] {
167 &self.v
168 }
169}
170
171impl IsPolyline for AngledPolyline {
172 fn into_iter_vec2<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = Vec2> + 'a> {
173 Box::new(self.v.iter().map(|x| x.loc()))
174 }
175
176 fn as_polyline(self) -> Polyline {
177 self.into_iter_vec2().collect_vec().as_polyline()
179 }
180
181 fn into_vec(self) -> Vec<Vec2> {
183 self.into_iter_vec2().collect_vec()
184 }
185
186 fn clone_to_vec(&self) -> Vec<Vec2> {
187 self.into_iter_vec2().collect_vec()
188 }
189}
190
191pub trait IsAngledPolyline {
192 fn into_iter_spot<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = SpotOnCurve> + 'a>;
193 fn as_angled_polyline(self) -> AngledPolyline;
194 fn into_vec(self) -> Vec<SpotOnCurve>;
195 fn clone_to_spot_vec(&self) -> Vec<SpotOnCurve> {
196 self.into_iter_spot().collect_vec()
197 }
198}
199
200impl IsAngledPolyline for &[SpotOnCurve] {
201 fn into_iter_spot<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = SpotOnCurve> + 'a> {
202 Box::new(self.iter().cloned())
203 }
204
205 fn as_angled_polyline(self) -> AngledPolyline {
206 AngledPolyline { v: self.to_vec() }
207 }
208
209 fn into_vec(self) -> Vec<SpotOnCurve> {
210 self.to_vec()
211 }
212}
213
214impl IsAngledPolyline for Vec<SpotOnCurve> {
215 fn into_iter_spot<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = SpotOnCurve> + 'a> {
216 Box::new(self.iter().cloned())
217 }
218
219 fn as_angled_polyline(self) -> AngledPolyline {
220 AngledPolyline { v: self.to_vec() }
221 }
222
223 fn into_vec(self) -> Vec<SpotOnCurve> {
224 self.to_vec()
225 }
226}
227
228impl IsAngledPolyline for AngledPolyline {
229 fn into_iter_spot<'a>(&'a self) -> Box<dyn ExactSizeIterator<Item = SpotOnCurve> + 'a> {
230 Box::new(self.v.iter().cloned())
231 }
232
233 fn as_angled_polyline(self) -> AngledPolyline {
234 self
235 }
236
237 fn into_vec(self) -> Vec<SpotOnCurve> {
238 self.v
239 }
240}