Skip to content

Commit 3e8f536

Browse files
committed
Implement method to clamp mesh
1 parent 3570753 commit 3e8f536

1 file changed

Lines changed: 84 additions & 1 deletion

File tree

splashsurf_lib/src/mesh.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! - `From<T> for UnstructuredGridPiece` implementations for the basic mesh types
1717
//! - `Into<DataSet>` implementations for the basic mesh types
1818
19-
use crate::{new_map, Real};
19+
use crate::{new_map, Aabb3d, MapType, Real};
2020
use bytemuck_derive::{Pod, Zeroable};
2121
use nalgebra::{Unit, Vector3};
2222
use rayon::prelude::*;
@@ -223,6 +223,89 @@ impl<R: Real> TriMesh3d<R> {
223223
}
224224
}
225225

226+
/// Returns a new triangle mesh containing only the specified triangles and removes all unreferenced vertices
227+
pub fn keep_tris(&self, cell_indices: &[usize]) -> Self {
228+
// Each entry is true if this vertex should be kept, false otherwise
229+
let vertex_keep_table = {
230+
let mut table = vec![false; self.vertices.len()];
231+
for &cell_index in cell_indices {
232+
let cell_connectivity = &self.triangles[cell_index];
233+
234+
for &vertex_index in cell_connectivity {
235+
table[vertex_index] = true;
236+
}
237+
}
238+
table
239+
};
240+
241+
let old_to_new_label_map = {
242+
let mut label_map = MapType::default();
243+
let mut next_label = 0;
244+
for (i, keep) in vertex_keep_table.iter().enumerate() {
245+
if *keep {
246+
label_map.insert(i, next_label);
247+
next_label += 1;
248+
}
249+
}
250+
label_map
251+
};
252+
253+
let relabeled_cells: Vec<_> = cell_indices
254+
.iter()
255+
.map(|&i| self.triangles[i].clone())
256+
.map(|mut cell| {
257+
for index in &mut cell {
258+
*index = *old_to_new_label_map
259+
.get(index)
260+
.expect("Index must be in map");
261+
}
262+
cell
263+
})
264+
.collect();
265+
266+
let relabeled_vertices: Vec<_> = vertex_keep_table
267+
.iter()
268+
.enumerate()
269+
.filter_map(|(i, should_keep)| if *should_keep { Some(i) } else { None })
270+
.map(|index| self.vertices[index].clone())
271+
.collect();
272+
273+
Self {
274+
vertices: relabeled_vertices,
275+
triangles: relabeled_cells,
276+
}
277+
}
278+
279+
/// Removes all triangles from the mesh that are completely outside of the given AABB and clamps the remaining triangles to the boundary
280+
pub fn clamp_with_aabb(&mut self, aabb: &Aabb3d<R>) {
281+
// Find all triangles with at least one vertex inside of AABB
282+
let triangles_to_keep = self
283+
.triangles
284+
.par_iter()
285+
.enumerate()
286+
.filter(|(_, tri)| tri.iter().any(|&v| aabb.contains_point(&self.vertices[v])))
287+
.map(|(i, _)| i)
288+
.collect::<Vec<_>>();
289+
// Remove all other triangles from mesh
290+
let new_mesh = self.keep_tris(&triangles_to_keep);
291+
// Replace current mesh
292+
let TriMesh3d {
293+
vertices,
294+
triangles,
295+
} = new_mesh;
296+
self.vertices = vertices;
297+
self.triangles = triangles;
298+
299+
// Clamp remaining vertices to AABB
300+
self.vertices.par_iter_mut().for_each(|v| {
301+
let min = aabb.min();
302+
let max = aabb.max();
303+
v.x = v.x.clamp(min.x, max.x);
304+
v.y = v.y.clamp(min.y, max.y);
305+
v.z = v.z.clamp(min.z, max.z);
306+
})
307+
}
308+
226309
/// Same as [`Self::vertex_normal_directions_inplace`] but assumes that the output is already zeroed
227310
fn vertex_normal_directions_inplace_assume_zeroed(&self, normal_directions: &mut [Vector3<R>]) {
228311
assert_eq!(normal_directions.len(), self.vertices.len());

0 commit comments

Comments
 (0)