honeycomb_kernels/remeshing/
relaxation.rs1use honeycomb_core::{
2 cmap::{CMap2, CMap3, VertexIdType},
3 geometry::{CoordsFloat, Vector2, Vector3},
4 stm::{StmClosureResult, Transaction},
5};
6
7#[inline]
33pub fn move_vertex_to_average<T: CoordsFloat>(
34 t: &mut Transaction,
35 map: &CMap2<T>,
36 vid: VertexIdType,
37 others: &[VertexIdType],
38) -> StmClosureResult<()> {
39 neighbor_based_smooth(t, map, vid, others, T::one())
40}
41
42#[inline]
69pub fn neighbor_based_smooth<T: CoordsFloat>(
70 t: &mut Transaction,
71 map: &CMap2<T>,
72 vid: VertexIdType,
73 neighbors_id: &[VertexIdType],
74 lambda: T,
75) -> StmClosureResult<()> {
76 let p = map
77 .read_vertex_tx(t, vid)?
78 .expect("E: no coordinates associated to vertex ID");
79
80 let n = neighbors_id.len();
81 let mut neighbors: smallvec::SmallVec<_, 16> = smallvec::SmallVec::with_capacity(n);
82 for &nid in neighbors_id {
83 neighbors.push(
84 map.read_vertex_tx(t, nid)?
85 .expect("E: no coordinates associated to vertex ID"),
86 );
87 }
88
89 let delta = neighbors
90 .into_iter()
91 .map(|v| v - p)
92 .fold(Vector2::default(), |a, b| a + b)
93 * lambda
94 / T::from(n).unwrap();
95
96 map.write_vertex_tx(t, vid, p + delta)?;
97
98 Ok(())
99}
100
101#[inline]
111pub fn move_vertex_to_average_3d<T: CoordsFloat>(
112 t: &mut Transaction,
113 map: &CMap3<T>,
114 vid: VertexIdType,
115 others: &[VertexIdType],
116) -> StmClosureResult<()> {
117 neighbor_based_smooth_3d(t, map, vid, others, T::one())
118}
119
120#[inline]
130pub fn neighbor_based_smooth_3d<T: CoordsFloat>(
131 t: &mut Transaction,
132 map: &CMap3<T>,
133 vid: VertexIdType,
134 neighbors_id: &[VertexIdType],
135 lambda: T,
136) -> StmClosureResult<()> {
137 let p = map
138 .read_vertex_tx(t, vid)?
139 .expect("E: no coordinates associated to vertex ID");
140
141 let n = neighbors_id.len();
142 let mut neighbors: smallvec::SmallVec<_, 16> = smallvec::SmallVec::with_capacity(n);
143 for &nid in neighbors_id {
144 neighbors.push(
145 map.read_vertex_tx(t, nid)?
146 .expect("E: no coordinates associated to vertex ID"),
147 );
148 }
149
150 let delta = neighbors
151 .into_iter()
152 .map(|v| v - p)
153 .fold(Vector3::default(), |a, b| a + b)
154 * lambda
155 / T::from(n).unwrap();
156
157 map.write_vertex_tx(t, vid, p + delta)?;
158
159 Ok(())
160}
161
162#[cfg(test)]
163mod tests {
164 use honeycomb_core::{
165 cmap::{CMap3, CMapBuilder},
166 geometry::Vertex3,
167 stm::atomically,
168 };
169
170 use super::{move_vertex_to_average_3d, neighbor_based_smooth_3d};
171
172 #[test]
173 fn smooth_vertices_3d() {
174 let map: CMap3<f64> = CMapBuilder::<3>::from_n_darts(3).build().unwrap();
175 map.set_vertex(1, Vertex3(0.0, 0.0, 0.0));
176 map.set_vertex(2, Vertex3(2.0, 0.0, 0.0));
177 map.set_vertex(3, Vertex3(0.0, 2.0, 2.0));
178
179 atomically(|transaction| move_vertex_to_average_3d(transaction, &map, 1, &[2, 3]));
180 assert_eq!(map.read_vertex(1), Some(Vertex3(1.0, 1.0, 1.0)));
181
182 map.set_vertex(1, Vertex3(0.0, 0.0, 0.0));
183 atomically(|transaction| neighbor_based_smooth_3d(transaction, &map, 1, &[2, 3], 0.5));
184 assert_eq!(map.read_vertex(1), Some(Vertex3(0.5, 0.5, 0.5)));
185 }
186}