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 x(&self) -> T {
66 self.0
67 }
68
69 pub fn y(&self) -> T {
71 self.1
72 }
73
74 pub fn average(lhs: &Vertex2<T>, rhs: &Vertex2<T>) -> Vertex2<T> {
92 let two = T::from(2.0).unwrap();
93 Vertex2((lhs.0 + rhs.0) / two, (lhs.1 + rhs.1) / two)
94 }
95
96 pub fn cross_product_from_vertices(v1: &Self, v2: &Self, v3: &Self) -> T {
98 (v2.x() - v1.x()) * (v3.y() - v2.y()) - (v2.y() - v1.y()) * (v3.x() - v2.x())
99 }
100}
101
102impl<T: CoordsFloat> From<(T, T)> for Vertex2<T> {
105 fn from((x, y): (T, T)) -> Self {
106 Self(x, y)
107 }
108}
109
110impl<T: CoordsFloat> std::ops::Add<Vector2<T>> for Vertex2<T> {
115 type Output = Self;
117
118 fn add(self, rhs: Vector2<T>) -> Self::Output {
119 Self(self.0 + rhs.0, self.1 + rhs.1)
120 }
121}
122
123impl<T: CoordsFloat> std::ops::AddAssign<Vector2<T>> for Vertex2<T> {
124 fn add_assign(&mut self, rhs: Vector2<T>) {
125 self.0 += rhs.0;
126 self.1 += rhs.1;
127 }
128}
129
130impl<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::Sub<Vector2<T>> for Vertex2<T> {
149 type Output = Self;
151
152 fn sub(self, rhs: Vector2<T>) -> Self::Output {
153 Self(self.0 - rhs.0, self.1 - rhs.1)
154 }
155}
156
157impl<T: CoordsFloat> std::ops::SubAssign<Vector2<T>> for Vertex2<T> {
158 fn sub_assign(&mut self, rhs: Vector2<T>) {
159 self.0 -= rhs.0;
160 self.1 -= rhs.1;
161 }
162}
163
164impl<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<Vertex2<T>> for Vertex2<T> {
181 type Output = Vector2<T>;
182
183 fn sub(self, rhs: Vertex2<T>) -> Self::Output {
184 Vector2(self.0 - rhs.0, self.1 - rhs.1)
185 }
186}
187
188impl<T: CoordsFloat> AttributeUpdate for Vertex2<T> {
189 fn merge(attr1: Self, attr2: Self) -> Result<Self, AttributeError> {
190 Ok(Self::average(&attr1, &attr2))
191 }
192
193 fn split(attr: Self) -> Result<(Self, Self), AttributeError> {
194 Ok((attr, attr))
195 }
196
197 fn merge_incomplete(attr: Self) -> Result<Self, AttributeError> {
199 Ok(attr)
200 }
201}
202
203impl<T: CoordsFloat> AttributeBind for Vertex2<T> {
204 type StorageType = AttrSparseVec<Self>;
205 type IdentifierType = VertexIdType;
206 const BIND_POLICY: OrbitPolicy = OrbitPolicy::Vertex;
207}