@@ -310,20 +310,91 @@ where
310310 }
311311
312312 /// Returns a new mesh containing only the specified cells and removes all unreferenced vertices
313- fn keep_cells ( & self , cell_indices : & [ usize ] ) -> Self {
313+ fn keep_cells ( & self , cell_indices : & [ usize ] , keep_vertices : bool ) -> Self {
314+ if keep_vertices {
315+ keep_cells_impl ( self , cell_indices, & [ ] )
316+ } else {
317+ let vertex_keep_table = vertex_keep_table ( self , cell_indices) ;
318+ keep_cells_impl ( self , cell_indices, & vertex_keep_table)
319+ }
320+ }
321+
322+ /// Removes all cells from the mesh that are completely outside of the given AABB and clamps the remaining cells to the boundary
323+ fn par_clamp_with_aabb (
324+ & self ,
325+ aabb : & Aabb3d < R > ,
326+ clamp_vertices : bool ,
327+ keep_vertices : bool ,
328+ ) -> Self
329+ where
330+ Self :: Cell : Sync ,
331+ {
332+ // Find all triangles with at least one vertex inside of AABB
314333 let vertices = self . vertices ( ) ;
315- let cells = self . cells ( ) ;
316-
317- // Each entry is true if this vertex should be kept, false otherwise
318- let vertex_keep_table = {
319- let mut table = vec ! [ false ; vertices. len( ) ] ;
320- for cell in cell_indices. iter ( ) . copied ( ) . map ( |c_i| & cells[ c_i] ) {
321- for & vertex_index in cell. vertices ( ) {
322- table[ vertex_index] = true ;
323- }
334+ let cells_to_keep = self
335+ . cells ( )
336+ . par_iter ( )
337+ . enumerate ( )
338+ . filter ( |( _, cell) | {
339+ cell. vertices ( )
340+ . iter ( )
341+ . copied ( )
342+ . any ( |v| aabb. contains_point ( & vertices[ v] ) )
343+ } )
344+ . map ( |( i, _) | i)
345+ . collect :: < Vec < _ > > ( ) ;
346+ // Remove all other cells from mesh
347+ let mut new_mesh = self . keep_cells ( & cells_to_keep, keep_vertices) ;
348+ // Clamp remaining vertices to AABB
349+ if clamp_vertices {
350+ new_mesh. vertices_mut ( ) . par_iter_mut ( ) . for_each ( |v| {
351+ let min = aabb. min ( ) ;
352+ let max = aabb. max ( ) ;
353+ v. x = v. x . clamp ( min. x , max. x ) ;
354+ v. y = v. y . clamp ( min. y , max. y ) ;
355+ v. z = v. z . clamp ( min. z , max. z ) ;
356+ } ) ;
357+ }
358+
359+ new_mesh
360+ }
361+ }
362+
363+ /// Returns the list of vertices that should remain in the given mesh after keeping only the given cells
364+ fn vertex_keep_table < R : Real , MeshT : Mesh3d < R > > ( mesh : & MeshT , cell_indices : & [ usize ] ) -> Vec < bool > {
365+ let vertices = mesh. vertices ( ) ;
366+ let cells = mesh. cells ( ) ;
367+
368+ // Each entry is true if this vertex should be kept, false otherwise
369+ let vertex_keep_table = {
370+ let mut table = vec ! [ false ; vertices. len( ) ] ;
371+ for cell in cell_indices. iter ( ) . copied ( ) . map ( |c_i| & cells[ c_i] ) {
372+ for & vertex_index in cell. vertices ( ) {
373+ table[ vertex_index] = true ;
324374 }
325- table
326- } ;
375+ }
376+ table
377+ } ;
378+
379+ vertex_keep_table
380+ }
381+
382+ /// Returns a new mesh keeping only the given cells and vertices in the mesh
383+ fn keep_cells_impl < R : Real , MeshT : Mesh3d < R > > (
384+ mesh : & MeshT ,
385+ cell_indices : & [ usize ] ,
386+ vertex_keep_table : & [ bool ] ,
387+ ) -> MeshT {
388+ let vertices = mesh. vertices ( ) ;
389+ let cells = mesh. cells ( ) ;
390+
391+ if vertex_keep_table. is_empty ( ) {
392+ MeshT :: from_vertices_and_connectivity (
393+ mesh. vertices ( ) . to_vec ( ) ,
394+ cell_indices. iter ( ) . map ( |& i| & cells[ i] ) . cloned ( ) . collect ( ) ,
395+ )
396+ } else {
397+ assert_eq ! ( mesh. vertices( ) . len( ) , vertex_keep_table. len( ) ) ;
327398
328399 let old_to_new_label_map = {
329400 let mut label_map = MapType :: default ( ) ;
@@ -353,45 +424,13 @@ where
353424
354425 let relabeled_vertices: Vec < _ > = vertex_keep_table
355426 . iter ( )
427+ . copied ( )
356428 . enumerate ( )
357- . filter_map ( |( i, should_keep) | if * should_keep { Some ( i) } else { None } )
429+ . filter_map ( |( i, should_keep) | if should_keep { Some ( i) } else { None } )
358430 . map ( |index| vertices[ index] . clone ( ) )
359431 . collect ( ) ;
360432
361- Self :: from_vertices_and_connectivity ( relabeled_vertices, relabeled_cells)
362- }
363-
364- /// Removes all cells from the mesh that are completely outside of the given AABB and clamps the remaining cells to the boundary
365- fn par_clamp_with_aabb ( & self , aabb : & Aabb3d < R > ) -> Self
366- where
367- Self :: Cell : Sync ,
368- {
369- // Find all triangles with at least one vertex inside of AABB
370- let vertices = self . vertices ( ) ;
371- let cells_to_keep = self
372- . cells ( )
373- . par_iter ( )
374- . enumerate ( )
375- . filter ( |( _, cell) | {
376- cell. vertices ( )
377- . iter ( )
378- . copied ( )
379- . any ( |v| aabb. contains_point ( & vertices[ v] ) )
380- } )
381- . map ( |( i, _) | i)
382- . collect :: < Vec < _ > > ( ) ;
383- // Remove all other cells from mesh
384- let mut new_mesh = self . keep_cells ( & cells_to_keep) ;
385- // Clamp remaining vertices to AABB
386- new_mesh. vertices_mut ( ) . par_iter_mut ( ) . for_each ( |v| {
387- let min = aabb. min ( ) ;
388- let max = aabb. max ( ) ;
389- v. x = v. x . clamp ( min. x , max. x ) ;
390- v. y = v. y . clamp ( min. y , max. y ) ;
391- v. z = v. z . clamp ( min. z , max. z ) ;
392- } ) ;
393-
394- new_mesh
433+ MeshT :: from_vertices_and_connectivity ( relabeled_vertices, relabeled_cells)
395434 }
396435}
397436
@@ -927,6 +966,45 @@ impl<R: Real, MeshT: Mesh3d<R>> Mesh3d<R> for MeshWithData<R, MeshT> {
927966 connectivity,
928967 ) )
929968 }
969+
970+ /// Returns a new mesh containing only the specified cells and removes all unreferenced vertices and attributes
971+ fn keep_cells ( & self , cell_indices : & [ usize ] , keep_all_vertices : bool ) -> Self {
972+ // Filter internal mesh
973+ let mut new_mesh = if keep_all_vertices {
974+ let mut new_mesh = keep_cells_impl ( self , cell_indices, & [ ] ) ;
975+ new_mesh. point_attributes = self . point_attributes . clone ( ) ;
976+ new_mesh
977+ } else {
978+ let vertex_keep_table = vertex_keep_table ( self , cell_indices) ;
979+ let mut new_mesh = keep_cells_impl ( self , cell_indices, & vertex_keep_table) ;
980+
981+ let vertex_indices = vertex_keep_table
982+ . iter ( )
983+ . copied ( )
984+ . enumerate ( )
985+ . filter_map ( |( i, should_keep) | if should_keep { Some ( i) } else { None } )
986+ . collect :: < Vec < _ > > ( ) ;
987+
988+ // Filter the point attributes
989+ new_mesh. point_attributes = self
990+ . point_attributes
991+ . iter ( )
992+ . map ( |attr| attr. keep_indices ( & vertex_indices) )
993+ . collect ( ) ;
994+
995+ new_mesh
996+ } ;
997+
998+ // Filter the cell attributes
999+ let cell_attributes = self
1000+ . cell_attributes
1001+ . iter ( )
1002+ . map ( |attr| attr. keep_indices ( & cell_indices) )
1003+ . collect ( ) ;
1004+ new_mesh. cell_attributes = cell_attributes;
1005+
1006+ new_mesh
1007+ }
9301008}
9311009
9321010/// Returns an mesh data wrapper with a default mesh and without attached attributes
@@ -1026,6 +1104,26 @@ impl<R: Real> MeshAttribute<R> {
10261104 . with_data ( vec3r_vec. iter ( ) . flatten ( ) . copied ( ) . collect :: < Vec < R > > ( ) ) ,
10271105 }
10281106 }
1107+
1108+ /// Returns a new attribute keeping only the entries with the given index
1109+ fn keep_indices ( & self , indices : & [ usize ] ) -> Self {
1110+ let data = match & self . data {
1111+ AttributeData :: ScalarU64 ( d) => {
1112+ AttributeData :: ScalarU64 ( indices. iter ( ) . copied ( ) . map ( |i| d[ i] . clone ( ) ) . collect ( ) )
1113+ }
1114+ AttributeData :: ScalarReal ( d) => {
1115+ AttributeData :: ScalarReal ( indices. iter ( ) . copied ( ) . map ( |i| d[ i] . clone ( ) ) . collect ( ) )
1116+ }
1117+ AttributeData :: Vector3Real ( d) => {
1118+ AttributeData :: Vector3Real ( indices. iter ( ) . copied ( ) . map ( |i| d[ i] . clone ( ) ) . collect ( ) )
1119+ }
1120+ } ;
1121+
1122+ Self {
1123+ name : self . name . clone ( ) ,
1124+ data,
1125+ }
1126+ }
10291127}
10301128
10311129impl < R : Real > AttributeData < R > {
0 commit comments