@@ -25,6 +25,7 @@ static ARGS_ADV: &str = "Advanced parameters";
2525static ARGS_OCTREE : & str = "Octree (domain decomposition) parameters" ;
2626static ARGS_DEBUG : & str = "Debug options" ;
2727static ARGS_INTERP : & str = "Interpolation" ;
28+ static ARGS_POSTPROC : & str = "Postprocessing" ;
2829static ARGS_OTHER : & str = "Remaining options" ;
2930
3031/// Command line arguments for the `reconstruct` subcommand
@@ -207,6 +208,27 @@ pub struct ReconstructSubcommandArgs {
207208 #[ arg( help_heading = ARGS_INTERP , long) ]
208209 pub interpolate_attributes : Vec < String > ,
209210
211+ /// Lower corner of the bounding-box for the surface mesh, mesh outside gets cut away (requires mesh-max to be specified)
212+ #[ arg(
213+ help_heading = ARGS_POSTPROC ,
214+ long,
215+ number_of_values = 3 ,
216+ value_names = [ "X_MIN" , "Y_MIN" , "Z_MIN" ] ,
217+ allow_negative_numbers = true ,
218+ requires = "mesh_aabb_max" ,
219+ ) ]
220+ pub mesh_aabb_min : Option < Vec < f64 > > ,
221+ /// Upper corner of the bounding-box for the surface mesh, mesh outside gets cut away (requires mesh-min to be specified)
222+ #[ arg(
223+ help_heading = ARGS_POSTPROC ,
224+ long,
225+ number_of_values = 3 ,
226+ value_names = [ "X_MIN" , "Y_MIN" , "Z_MIN" ] ,
227+ allow_negative_numbers = true ,
228+ requires = "mesh_aabb_min" ,
229+ ) ]
230+ pub mesh_aabb_max : Option < Vec < f64 > > ,
231+
210232 /// Optional filename for writing the point cloud representation of the intermediate density map to disk
211233 #[ arg( help_heading = ARGS_DEBUG , long, value_parser = value_parser!( PathBuf ) ) ]
212234 pub output_dm_points : Option < PathBuf > ,
@@ -324,6 +346,7 @@ mod arguments {
324346 pub compute_normals : bool ,
325347 pub sph_normals : bool ,
326348 pub interpolate_attributes : Vec < String > ,
349+ pub mesh_aabb : Option < Aabb3d < f64 > > ,
327350 }
328351
329352 /// All arguments that can be supplied to the surface reconstruction tool converted to useful types
@@ -381,6 +404,15 @@ mod arguments {
381404 None
382405 } ;
383406
407+ // Convert mesh domain args to aabb
408+ let mesh_aabb = if let ( Some ( mesh_min) , Some ( mesh_max) ) =
409+ ( & args. mesh_aabb_min , & args. mesh_aabb_max )
410+ {
411+ Some ( try_aabb_from_min_max ( mesh_min, mesh_max, "mesh AABB" ) ?)
412+ } else {
413+ None
414+ } ;
415+
384416 // Scale kernel radius and cube size by particle radius
385417 let compact_support_radius = args. particle_radius * 2.0 * args. smoothing_length ;
386418 let cube_size = args. particle_radius * args. cube_size ;
@@ -448,6 +480,7 @@ mod arguments {
448480 compute_normals : args. normals . into_bool ( ) ,
449481 sph_normals : args. sph_normals . into_bool ( ) ,
450482 interpolate_attributes : args. interpolate_attributes . clone ( ) ,
483+ mesh_aabb,
451484 } ;
452485
453486 Ok ( ReconstructionRunnerArgs {
@@ -835,6 +868,21 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
835868 let grid = reconstruction. grid ( ) ;
836869 let mesh = reconstruction. mesh ( ) ;
837870
871+ let mesh = if let Some ( aabb) = & postprocessing. mesh_aabb {
872+ profile ! ( "clamp mesh to aabb" ) ;
873+ info ! ( "Post-processing: Clamping mesh to AABB..." ) ;
874+
875+ let mut mesh = mesh. clone ( ) ;
876+ mesh. clamp_with_aabb (
877+ & aabb
878+ . try_convert ( )
879+ . ok_or_else ( || anyhow ! ( "Failed to convert mesh AABB" ) ) ?,
880+ ) ;
881+ mesh
882+ } else {
883+ mesh. clone ( )
884+ } ;
885+
838886 // Add normals to mesh if requested
839887 let mesh = if postprocessing. compute_normals || !attributes. is_empty ( ) {
840888 profile ! ( "compute normals" ) ;
@@ -866,7 +914,8 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
866914 params. compact_support_radius ,
867915 ) ;
868916
869- let mut mesh_with_data = MeshWithData :: new ( mesh. clone ( ) ) ;
917+ let mut mesh_with_data = MeshWithData :: new ( mesh) ;
918+ let mesh = & mesh_with_data. mesh ;
870919
871920 // Compute normals if requested
872921 if postprocessing. compute_normals {
@@ -925,7 +974,7 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
925974
926975 mesh_with_data
927976 } else {
928- MeshWithData :: new ( mesh. clone ( ) )
977+ MeshWithData :: new ( mesh)
929978 } ;
930979
931980 // Store the surface mesh
0 commit comments