@@ -1016,6 +1016,25 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
10161016 // Perform the surface reconstruction
10171017 let reconstruction = splashsurf_lib:: reconstruct_surface :: < I , R > ( particle_positions, params) ?;
10181018
1019+ // Filters a particle quantity based on an optional mask of particles inside the reconstruction domain
1020+ fn filtered_quantity < ' a , T : Clone > (
1021+ values : & ' a [ T ] ,
1022+ particles_inside : Option < & [ bool ] > ,
1023+ ) -> Cow < ' a , [ T ] > {
1024+ if let Some ( particles_inside) = particles_inside {
1025+ assert_eq ! ( values. len( ) , particles_inside. len( ) ) ;
1026+ let filtered_values = values
1027+ . iter ( )
1028+ . zip ( particles_inside. iter ( ) . copied ( ) )
1029+ . filter ( |( _, is_inside) | * is_inside)
1030+ . map ( |( v, _) | v. clone ( ) )
1031+ . collect :: < Vec < _ > > ( ) ;
1032+ Cow :: Owned ( filtered_values)
1033+ } else {
1034+ Cow :: Borrowed ( values)
1035+ }
1036+ }
1037+
10191038 let reconstruction_output = if postprocessing. output_raw_mesh {
10201039 Some ( reconstruction. clone ( ) )
10211040 } else {
@@ -1070,6 +1089,17 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
10701089 . as_ref ( )
10711090 . map ( Vec :: is_empty)
10721091 . unwrap_or ( true ) ) ;
1092+ let filtered_particle_positions_cow = if interpolator_required {
1093+ // TODO: Re-use filtered particles from reconstruction?
1094+ filtered_quantity (
1095+ particle_positions,
1096+ reconstruction. particle_inside_aabb ( ) . map ( Vec :: as_slice) ,
1097+ )
1098+ } else {
1099+ Cow :: Borrowed ( particle_positions)
1100+ } ;
1101+ let filtered_particle_positions = filtered_particle_positions_cow. as_ref ( ) ;
1102+
10731103 let interpolator = if interpolator_required {
10741104 profile ! ( "initialize interpolator" ) ;
10751105 info ! ( "Post-processing: Initializing interpolator..." ) ;
@@ -1089,13 +1119,13 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
10891119 . ok_or_else ( || anyhow:: anyhow!( "Particle densities were not returned by surface reconstruction but are required for SPH normal computation" ) ) ?
10901120 . as_slice ( ) ;
10911121 assert_eq ! (
1092- particle_positions . len( ) ,
1122+ filtered_particle_positions . len( ) ,
10931123 particle_densities. len( ) ,
10941124 "There has to be one density value per particle"
10951125 ) ;
10961126
10971127 Some ( SphInterpolator :: new (
1098- & particle_positions ,
1128+ & filtered_particle_positions ,
10991129 particle_densities,
11001130 particle_rest_mass,
11011131 params. compact_support_radius ,
@@ -1127,17 +1157,17 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
11271157 {
11281158 let search_radius = params. compact_support_radius ;
11291159
1130- let mut domain = Aabb3d :: from_points ( particle_positions ) ;
1160+ let mut domain = Aabb3d :: from_points ( filtered_particle_positions ) ;
11311161 domain. grow_uniformly ( search_radius) ;
11321162
11331163 let mut nl = Vec :: new ( ) ;
11341164 splashsurf_lib:: neighborhood_search:: neighborhood_search_spatial_hashing_parallel :: < I , R > (
11351165 & domain,
1136- particle_positions ,
1166+ filtered_particle_positions ,
11371167 search_radius,
11381168 & mut nl,
11391169 ) ;
1140- assert_eq ! ( nl. len( ) , particle_positions . len( ) ) ;
1170+ assert_eq ! ( nl. len( ) , filtered_particle_positions . len( ) ) ;
11411171 Cow :: Owned ( nl)
11421172 }
11431173 ) ;
@@ -1151,8 +1181,9 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
11511181 nl. iter ( )
11521182 . copied ( )
11531183 . map ( |j| {
1154- let dist =
1155- ( particle_positions[ i] - particle_positions[ j] ) . norm_squared ( ) ;
1184+ let dist = ( filtered_particle_positions[ i]
1185+ - filtered_particle_positions[ j] )
1186+ . norm_squared ( ) ;
11561187
11571188 R :: one ( ) - ( dist / squared_r) . clamp ( R :: zero ( ) , R :: one ( ) )
11581189 } )
@@ -1299,10 +1330,12 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
12991330 {
13001331 info ! ( "Interpolating attribute \" {}\" ..." , attribute. name) ;
13011332
1333+ let particles_inside = reconstruction. particle_inside_aabb ( ) . map ( Vec :: as_slice) ;
13021334 match & attribute. data {
13031335 AttributeData :: ScalarReal ( values) => {
1336+ let filtered_values = filtered_quantity ( values, particles_inside) ;
13041337 let interpolated_values = interpolator. interpolate_scalar_quantity (
1305- values . as_slice ( ) ,
1338+ & filtered_values ,
13061339 mesh_with_data. vertices ( ) ,
13071340 true ,
13081341 ) ;
@@ -1312,8 +1345,9 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
13121345 ) ) ;
13131346 }
13141347 AttributeData :: Vector3Real ( values) => {
1348+ let filtered_values = filtered_quantity ( values, particles_inside) ;
13151349 let interpolated_values = interpolator. interpolate_vector_quantity (
1316- values . as_slice ( ) ,
1350+ & filtered_values ,
13171351 mesh_with_data. vertices ( ) ,
13181352 true ,
13191353 ) ;
0 commit comments