honeycomb_core/geometry/dim2/
vertex.rs1use crate::attributes::{AttrSparseVec, AttributeBind, AttributeError, AttributeUpdate};
6use crate::cmap::{OrbitPolicy, VertexIdType};
7use crate::geometry::{CoordsFloat, Vector2};
8
9#[derive(Debug, Clone, Copy, Default, PartialEq)]
53pub struct Vertex2<T: CoordsFloat>(pub T, pub T);
54
55unsafe impl<T: CoordsFloat> Send for Vertex2<T> {}
56unsafe impl<T: CoordsFloat> Sync for Vertex2<T> {}
57
58impl<T: CoordsFloat> Vertex2<T> {
59 pub fn into_inner(self) -> (T, T) {
61 (self.0, self.1)
62 }
63
64 pub fn to_f32(self) -> Option<Vertex2<f32>> {
66 match (self.0.to_f32(), self.1.to_f32()) {
67 (Some(x), Some(y)) => Some(Vertex2(x, y)),
68 _ => None,
69 }
70 }
71
72 pub fn to_f64(self) -> Option<Vertex2<f64>> {
74 match (self.0.to_f64(), self.1.to_f64()) {
75 (Some(x), Some(y)) => Some(Vertex2(x, y)),
76 _ => None,
77 }
78 }
79
80 pub fn x(&self) -> T {
82 self.0
83 }
84
85 pub fn y(&self) -> T {
87 self.1
88 }
89
90 pub fn average(lhs: &Vertex2<T>, rhs: &Vertex2<T>) -> Vertex2<T> {
108 let two = T::from(2.0).unwrap();
109 Vertex2((lhs.0 + rhs.0) / two, (lhs.1 + rhs.1) / two)
110 }
111
112 pub fn cross_product_from_vertices(v1: &Self, v2: &Self, v3: &Self) -> T {
114 (v2.x() - v1.x()) * (v3.y() - v2.y()) - (v2.y() - v1.y()) * (v3.x() - v2.x())
115 }
116}
117
118impl<T: CoordsFloat> From<(T, T)> for Vertex2<T> {
121 fn from((x, y): (T, T)) -> Self {
122 Self(x, y)
123 }
124}
125
126impl<T: CoordsFloat> std::ops::Add<Vector2<T>> for Vertex2<T> {
131 type Output = Self;
133
134 fn add(self, rhs: Vector2<T>) -> Self::Output {
135 Self(self.0 + rhs.0, self.1 + rhs.1)
136 }
137}
138
139impl<T: CoordsFloat> std::ops::AddAssign<Vector2<T>> for Vertex2<T> {
140 fn add_assign(&mut self, rhs: Vector2<T>) {
141 self.0 += rhs.0;
142 self.1 += rhs.1;
143 }
144}
145
146impl<T: CoordsFloat> std::ops::Add<&Vector2<T>> for Vertex2<T> {
147 type Output = Self;
149
150 fn add(self, rhs: &Vector2<T>) -> Self::Output {
151 Self(self.0 + rhs.0, self.1 + rhs.1)
152 }
153}
154
155impl<T: CoordsFloat> std::ops::AddAssign<&Vector2<T>> for Vertex2<T> {
156 fn add_assign(&mut self, rhs: &Vector2<T>) {
157 self.0 += rhs.0;
158 self.1 += rhs.1;
159 }
160}
161
162impl<T: CoordsFloat> std::ops::Sub<Vector2<T>> for Vertex2<T> {
165 type Output = Self;
167
168 fn sub(self, rhs: Vector2<T>) -> Self::Output {
169 Self(self.0 - rhs.0, self.1 - rhs.1)
170 }
171}
172
173impl<T: CoordsFloat> std::ops::SubAssign<Vector2<T>> for Vertex2<T> {
174 fn sub_assign(&mut self, rhs: Vector2<T>) {
175 self.0 -= rhs.0;
176 self.1 -= rhs.1;
177 }
178}
179
180impl<T: CoordsFloat> std::ops::Sub<&Vector2<T>> for Vertex2<T> {
181 type Output = Self;
183
184 fn sub(self, rhs: &Vector2<T>) -> Self::Output {
185 Self(self.0 - rhs.0, self.1 - rhs.1)
186 }
187}
188
189impl<T: CoordsFloat> std::ops::SubAssign<&Vector2<T>> for Vertex2<T> {
190 fn sub_assign(&mut self, rhs: &Vector2<T>) {
191 self.0 -= rhs.0;
192 self.1 -= rhs.1;
193 }
194}
195
196impl<T: CoordsFloat> std::ops::Sub<Vertex2<T>> for Vertex2<T> {
197 type Output = Vector2<T>;
198
199 fn sub(self, rhs: Vertex2<T>) -> Self::Output {
200 Vector2(self.0 - rhs.0, self.1 - rhs.1)
201 }
202}
203
204impl<T: CoordsFloat> AttributeUpdate for Vertex2<T> {
205 fn merge(attr1: Self, attr2: Self) -> Result<Self, AttributeError> {
206 Ok(Self::average(&attr1, &attr2))
207 }
208
209 fn split(attr: Self) -> Result<(Self, Self), AttributeError> {
210 Ok((attr, attr))
211 }
212
213 fn merge_incomplete(attr: Self) -> Result<Self, AttributeError> {
215 Ok(attr)
216 }
217}
218
219impl<T: CoordsFloat> AttributeBind for Vertex2<T> {
220 type StorageType = AttrSparseVec<Self>;
221 type IdentifierType = VertexIdType;
222 const BIND_POLICY: OrbitPolicy = OrbitPolicy::Vertex;
223}