mesh_graph/plane_slice/
polygon.rs1use std::collections::VecDeque;
2
3use glam::{Mat4, Vec2, Vec3, Vec4Swizzles};
4use itertools::Itertools;
5
6#[derive(Debug, Clone, Copy)]
7pub enum PolygonTerminal {
8 Start,
9 End,
10}
11
12#[derive(Debug, Clone, PartialEq)]
13pub struct Polygon2 {
14 pub vertices: VecDeque<Vec2>,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct Polygon3 {
19 pub vertices: VecDeque<Vec3>,
20}
21
22impl Polygon2 {
23 pub fn terminal(&self, terminal: PolygonTerminal) -> Option<Vec2> {
25 if self.vertices.is_empty() {
26 return None;
27 }
28
29 match terminal {
30 PolygonTerminal::Start => Some(self.vertices[0]),
31 PolygonTerminal::End => Some(self.vertices[self.vertices.len() - 1]),
32 }
33 }
34
35 pub fn extend_by_line(&mut self, terminal: PolygonTerminal, other_line_end: Vec2) {
37 match terminal {
38 PolygonTerminal::Start => self.vertices.push_front(other_line_end),
39 PolygonTerminal::End => self.vertices.push_back(other_line_end),
40 }
41 }
42
43 pub fn merge_polygon(
45 &mut self,
46 my_terminal: PolygonTerminal,
47 mut other: Polygon2,
48 other_terminal: PolygonTerminal,
49 ) {
50 let mut vertices = VecDeque::new();
51
52 match my_terminal {
53 PolygonTerminal::Start => {
54 match other_terminal {
55 PolygonTerminal::Start => vertices.extend(other.vertices.into_iter().rev()),
56 PolygonTerminal::End => vertices.append(&mut other.vertices),
57 }
58
59 vertices.append(&mut self.vertices);
60 }
61 PolygonTerminal::End => {
62 vertices.append(&mut self.vertices);
63
64 match other_terminal {
65 PolygonTerminal::Start => vertices.append(&mut other.vertices),
66 PolygonTerminal::End => vertices.extend(other.vertices.into_iter().rev()),
67 }
68 }
69 }
70
71 self.vertices = vertices;
72 }
73
74 pub fn is_closed(&self) -> bool {
76 if let (Some(front), Some(back)) = (self.vertices.front(), self.vertices.back()) {
77 front.distance_squared(*back) < 1e-6
78 } else {
79 false
80 }
81 }
82
83 pub fn close(&mut self) {
85 if !self.is_closed() {
86 self.vertices.push_back(self.vertices[0]);
87 }
88 }
89
90 pub fn length(&self) -> f32 {
92 self.vertices
93 .iter()
94 .array_windows()
95 .map(|[a, b]| a.distance(*b))
96 .sum()
97 }
98
99 #[cfg(feature = "rerun")]
100 pub fn log_rerun(&self, name: &str) {
101 use crate::utils::vec2_array;
102
103 crate::RR
104 .log(
105 name,
106 &rerun::LineStrips3D::new([self.vertices.iter().copied().map(vec2_array)]),
107 )
108 .unwrap();
109 }
110
111 pub fn min_max(&self) -> (Vec2, Vec2) {
116 let mut min = Vec2::MAX;
117 let mut max = Vec2::MIN;
118
119 for vertex in &self.vertices {
120 min = min.min(*vertex);
121 max = max.max(*vertex);
122 }
123
124 (min, max)
125 }
126
127 pub fn contains_point(&self, point: Vec2) -> bool {
131 let mut inside = false;
134
135 for (a, b) in self.vertices.iter().tuple_windows() {
136 if ((a.y > point.y) != (b.y > point.y))
137 && (point.x < (b.x - a.x) * (point.y - a.y) / (b.y - a.y) + a.x)
138 {
139 inside = !inside;
140 }
141 }
142
143 inside
144 }
145}
146
147impl Polygon3 {
148 pub fn from_polygon2_with_transform(polygon: Polygon2, transform: Mat4) -> Self {
149 let vertices = polygon
150 .vertices
151 .into_iter()
152 .map(|v| (transform * v.extend(0.0).extend(1.0)).xyz())
153 .collect();
154
155 Self { vertices }
156 }
157
158 pub fn length(&self) -> f32 {
160 self.vertices
161 .iter()
162 .array_windows()
163 .map(|[a, b]| a.distance(*b))
164 .sum()
165 }
166
167 #[cfg(feature = "rerun")]
168 pub fn log_rerun<'a>(
169 rr: &rerun::RecordingStream,
170 name: &str,
171 polygons: impl IntoIterator<Item = &'a Self>,
172 ) {
173 use crate::utils::vec3_array;
174
175 rr.log(
176 name,
177 &rerun::LineStrips3D::new(
178 polygons
179 .into_iter()
180 .map(|p| p.vertices.iter().copied().map(vec3_array)),
181 ),
182 )
183 .unwrap();
184 }
185}