1use super::{Float, Line2, Triangle, Vec2, PI};
2
3pub struct Polygon {
14 vertices: Vec<Vec2>,
15}
16
17impl Polygon {
18 pub fn new(vertices: Vec<Vec2>) -> Self {
20 Self { vertices }
21 }
22
23 pub fn empty() -> Self {
25 Self {
26 vertices: Vec::new(),
27 }
28 }
29
30 pub fn with_capacity(capacity: usize) -> Self {
32 Self {
33 vertices: Vec::with_capacity(capacity),
34 }
35 }
36
37 pub fn new_ngon(pos: Vec2, circumradius: Float, n: usize) -> Self {
39 if n < 3 {
40 panic!("Polygon must have at least 3 sides");
41 }
42
43 let mut poly = Self {
44 vertices: Vec::new(),
45 };
46
47 let angle = (2. * PI) / n as Float;
48
49 for i in 0..n {
50 let a = angle * i as Float + (PI / 2.);
52 let x = a.cos() * circumradius;
53 let y = a.sin() * circumradius;
54 poly.vertices.push(Vec2::new(x, y) + pos);
55 }
56 poly
57 }
58
59 pub fn add_vertex(&mut self, v: Vec2) {
61 self.vertices.push(v);
62 }
63
64 pub fn n(&self) -> usize {
66 self.vertices.len()
67 }
68
69 pub fn interior_angle(&self) -> Float {
71 let n = self.vertices.len() as Float;
72 ((n as Float - 2.) * PI) / n
73 }
74
75 pub fn vertices(&self) -> Vec<Vec2> {
77 self.vertices.clone()
78 }
79
80 pub fn edges(&self) -> Vec<Line2> {
82 let mut lines = Vec::new();
83 for (i, _) in self.vertices.iter().enumerate() {
84 lines.push(self.edge(i, true).unwrap());
85 }
86 lines
87 }
88
89 pub fn vertex(&self, i: usize) -> Option<Vec2> {
91 if i < self.vertices.len() {
92 return Some(self.vertices[i]);
93 }
94 return None;
95 }
96
97 pub fn is_convex(&self) -> bool {
99 let n = self.vertices.len();
100 if n < 3 {
101 true
102 } else {
103 let mut i = 0;
104 let l = n - 2;
105
106 while i < l {
107 let triangle = Triangle::new(
108 self.vertices[i],
109 self.vertices[i + 1],
110 self.vertices[i + 2],
111 );
112 if !triangle.is_convex() {
113 return false;
114 } else {
115 i += 3;
116 }
117 }
118
119 let triangle =
120 Triangle::new(self.vertices[l], self.vertices[l + 1], self.vertices[0]);
121 if !triangle.is_convex() {
122 return false;
123 }
124 let triangle =
125 Triangle::new(self.vertices[l + 1], self.vertices[0], self.vertices[1]);
126 if !triangle.is_convex() {
127 return false;
128 }
129 true
130 }
131 }
132
133 pub fn triangulate(&self) -> Vec<Triangle> {
136 let mut triangles = Vec::new();
137 let n = self.vertices.len();
138
139 if n < 3 {
140 return triangles;
142 }
143
144 if n == 3 {
145 triangles.push(Triangle::new(
147 self.vertices[0],
148 self.vertices[1],
149 self.vertices[2],
150 ));
151 return triangles;
152 }
153
154 let mut avl = Vec::with_capacity(n);
156
157 for i in 0..n {
158 avl.push(i);
159 }
160
161 let mut i = 0;
162 let mut al = n;
163 while al > 3 {
164 let i0 = avl[i % al];
165 let i1 = avl[(i + 1) % al];
166 let i2 = avl[(i + 2) % al];
167
168 let a = self.vertices[i0];
169 let b = self.vertices[i1];
170 let c = self.vertices[i2];
171
172 let t = Triangle::new(a, b, c);
173
174 let mut ear_found = false;
175 if t.is_convex() {
176 ear_found = true;
177
178 for j in 0..al {
179 let vi = avl[j];
180
181 if vi != i0 && vi != i1 && vi != i2 {
182 if t.contains_point(self.vertices[vi]) {
183 ear_found = false;
184 break;
185 }
186 }
187 }
188 }
189
190 if ear_found {
191 triangles.push(t);
192 avl.remove((i + 1) % al);
193 al -= 1;
194 i = 0;
195 } else if i > 3 * al {
196 break;
197 } else {
198 i += 1;
199 }
200 }
201
202 triangles.push(Triangle::new(
203 self.vertices[avl[0]],
204 self.vertices[avl[1]],
205 self.vertices[avl[2]],
206 ));
207 triangles
208 }
209
210 pub fn edge(&self, i: usize, clockwise: bool) -> Option<Line2> {
212 let vert_count = self.vertices.len();
213
214 if clockwise {
215 if i + 1 < vert_count {
216 return Some(Line2 {
217 a: self.vertices[i],
218 b: self.vertices[i + 1],
219 });
220 } else if i < vert_count {
221 return Some(Line2 {
222 a: self.vertices[i],
223 b: self.vertices[0],
224 });
225 }
226 } else {
227 if i < vert_count {
228 if i > 0 {
229 return Some(Line2 {
230 a: self.vertices[i],
231 b: self.vertices[i - 1],
232 });
233 } else {
234 return Some(Line2 {
235 a: self.vertices[i],
236 b: self.vertices[vert_count - 1],
237 });
238 }
239 }
240 }
241 return None;
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::Vec2;
248 use crate::geom::polygon::Polygon;
249
250 const POLY_SIZE: usize = 12;
251
252 #[test]
253 fn polygon_test() {
254 let poly = Polygon::new_ngon(Vec2::new(256., 256.), 200., POLY_SIZE);
255 assert_eq!(poly.n(), POLY_SIZE)
256 }
257}