@@ -15,6 +15,8 @@ use splashsurf_lib::{density_map, Index, Real};
1515use std:: convert:: TryFrom ;
1616use std:: path:: PathBuf ;
1717
18+ use arguments:: * ;
19+
1820// TODO: Detect smallest index type (i.e. check if ok to use i32 as index)
1921
2022static ARGS_IO : & str = "Input/output" ;
@@ -317,46 +319,66 @@ mod arguments {
317319 use std:: str:: FromStr ;
318320 use walkdir:: WalkDir ;
319321
322+ pub struct ReconstructionRunnerPostprocessingArgs {
323+ pub check_mesh : bool ,
324+ pub compute_normals : bool ,
325+ pub sph_normals : bool ,
326+ pub interpolate_attributes : Vec < String > ,
327+ }
328+
320329 /// All arguments that can be supplied to the surface reconstruction tool converted to useful types
321330 pub struct ReconstructionRunnerArgs {
322331 pub params : splashsurf_lib:: Parameters < f64 > ,
323332 pub use_double_precision : bool ,
324- pub check_mesh : bool ,
325333 pub io_params : io:: FormatParameters ,
334+ pub postprocessing : ReconstructionRunnerPostprocessingArgs ,
335+ }
336+
337+ fn try_aabb_from_min_max (
338+ min : & Vec < f64 > ,
339+ max : & Vec < f64 > ,
340+ error_str : & ' static str ,
341+ ) -> Result < Aabb3d < f64 > , anyhow:: Error > {
342+ // This should already be ensured by StructOpt parsing
343+ assert_eq ! ( min. len( ) , 3 ) ;
344+ assert_eq ! ( max. len( ) , 3 ) ;
345+
346+ let aabb = Aabb3d :: new (
347+ Vector3 :: from_iterator ( min. clone ( ) ) ,
348+ Vector3 :: from_iterator ( max. clone ( ) ) ,
349+ ) ;
350+
351+ if !aabb. is_consistent ( ) {
352+ return Err ( anyhow ! ( "The user specified {error_str} min/max values are inconsistent! min: {:?} max: {:?}" , aabb. min( ) . as_slice( ) , aabb. max( ) . as_slice( ) ) ) ;
353+ }
354+
355+ if aabb. is_degenerate ( ) {
356+ return Err ( anyhow ! (
357+ "The user specified {error_str} is degenerate! min: {:?} max: {:?}" ,
358+ aabb. min( ) . as_slice( ) ,
359+ aabb. max( ) . as_slice( )
360+ ) ) ;
361+ }
362+
363+ Ok ( aabb)
326364 }
327365
328366 // Convert raw command line arguments to more useful types
329367 impl TryFrom < & ReconstructSubcommandArgs > for ReconstructionRunnerArgs {
330368 type Error = anyhow:: Error ;
331369
332370 fn try_from ( args : & ReconstructSubcommandArgs ) -> Result < Self , Self :: Error > {
333- // Convert domain args to aabb
334- let domain_aabb = match ( & args. domain_min , & args. domain_max ) {
335- ( Some ( domain_min) , Some ( domain_max) ) => {
336- // This should already be ensured by StructOpt parsing
337- assert_eq ! ( domain_min. len( ) , 3 ) ;
338- assert_eq ! ( domain_max. len( ) , 3 ) ;
339-
340- let aabb = Aabb3d :: new (
341- Vector3 :: from_iterator ( domain_min. clone ( ) ) ,
342- Vector3 :: from_iterator ( domain_max. clone ( ) ) ,
343- ) ;
344-
345- if !aabb. is_consistent ( ) {
346- return Err ( anyhow ! ( "The user specified domain min/max values are inconsistent! min: {:?} max: {:?}" , aabb. min( ) . as_slice( ) , aabb. max( ) . as_slice( ) ) ) ;
347- }
348-
349- if aabb. is_degenerate ( ) {
350- return Err ( anyhow ! (
351- "The user specified domain is degenerate! min: {:?} max: {:?}" ,
352- aabb. min( ) . as_slice( ) ,
353- aabb. max( ) . as_slice( )
354- ) ) ;
355- }
356-
357- Some ( aabb)
358- }
359- _ => None ,
371+ // Convert particle domain args to aabb
372+ let domain_aabb = if let ( Some ( domain_min) , Some ( domain_max) ) =
373+ ( & args. domain_min , & args. domain_max )
374+ {
375+ Some ( try_aabb_from_min_max (
376+ domain_min,
377+ domain_max,
378+ "particle AABB" ,
379+ ) ?)
380+ } else {
381+ None
360382 } ;
361383
362384 // Scale kernel radius and cube size by particle radius
@@ -421,11 +443,18 @@ mod arguments {
421443 splashsurf_lib:: initialize_thread_pool ( num_threads) ?;
422444 }
423445
446+ let postprocessing = ReconstructionRunnerPostprocessingArgs {
447+ check_mesh : args. check_mesh . into_bool ( ) ,
448+ compute_normals : args. normals . into_bool ( ) ,
449+ sph_normals : args. sph_normals . into_bool ( ) ,
450+ interpolate_attributes : args. interpolate_attributes . clone ( ) ,
451+ } ;
452+
424453 Ok ( ReconstructionRunnerArgs {
425454 params,
426455 use_double_precision : args. double_precision . into_bool ( ) ,
427- check_mesh : args. check_mesh . into_bool ( ) ,
428456 io_params : io:: FormatParameters :: default ( ) ,
457+ postprocessing,
429458 } )
430459 }
431460 }
@@ -439,12 +468,6 @@ mod arguments {
439468 output_density_map_grid_file : Option < PathBuf > ,
440469 output_octree_file : Option < PathBuf > ,
441470 sequence_range : ( Option < usize > , Option < usize > ) ,
442- /// Whether to enable normal computation for all files
443- compute_normals : bool ,
444- /// Whether to use SPH interpolation to compute the normals for all files
445- sph_normals : bool ,
446- /// Additional attributes to load and interpolate to surface
447- attributes : Vec < String > ,
448471 }
449472
450473 impl ReconstructionRunnerPathCollection {
@@ -457,9 +480,6 @@ mod arguments {
457480 output_density_map_grid_file : Option < P > ,
458481 output_octree_file : Option < P > ,
459482 sequence_range : ( Option < usize > , Option < usize > ) ,
460- compute_normals : bool ,
461- sph_normals : bool ,
462- attributes : Vec < String > ,
463483 ) -> Result < Self , anyhow:: Error > {
464484 let input_file = input_file. into ( ) ;
465485 let output_base_path = output_base_path. map ( |p| p. into ( ) ) ;
@@ -504,9 +524,6 @@ mod arguments {
504524 . map ( |f| output_base_path. join ( f) ) ,
505525 output_octree_file : output_octree_file. map ( |f| output_base_path. join ( f) ) ,
506526 sequence_range,
507- compute_normals,
508- sph_normals,
509- attributes,
510527 } )
511528 } else {
512529 Ok ( Self {
@@ -517,9 +534,6 @@ mod arguments {
517534 output_density_map_grid_file,
518535 output_octree_file,
519536 sequence_range,
520- compute_normals,
521- sph_normals,
522- attributes,
523537 } )
524538 }
525539 }
@@ -605,9 +619,6 @@ mod arguments {
605619 None ,
606620 None ,
607621 None ,
608- self . compute_normals ,
609- self . sph_normals ,
610- self . attributes . clone ( ) ,
611622 ) ) ;
612623 }
613624 }
@@ -634,9 +645,6 @@ mod arguments {
634645 self . output_density_map_points_file. clone( ) ,
635646 self . output_density_map_grid_file. clone( ) ,
636647 self . output_octree_file. clone( ) ,
637- self . compute_normals,
638- self . sph_normals,
639- self . attributes. clone( ) ,
640648 ) ;
641649 1
642650 ]
@@ -737,9 +745,6 @@ mod arguments {
737745 args. output_dm_grid . clone ( ) ,
738746 args. output_octree . clone ( ) ,
739747 ( args. start_index , args. end_index ) ,
740- args. normals . into_bool ( ) ,
741- args. sph_normals . into_bool ( ) ,
742- args. interpolate_attributes . clone ( ) ,
743748 )
744749 }
745750 }
@@ -752,12 +757,6 @@ mod arguments {
752757 pub output_density_map_points_file : Option < PathBuf > ,
753758 pub output_density_map_grid_file : Option < PathBuf > ,
754759 pub output_octree_file : Option < PathBuf > ,
755- /// Whether to enable normal computation
756- pub compute_normals : bool ,
757- /// Whether to use SPH interpolation to compute the normals
758- pub sph_normals : bool ,
759- /// Additional attributes to load and interpolate to surface
760- pub attributes : Vec < String > ,
761760 }
762761
763762 impl ReconstructionRunnerPaths {
@@ -767,19 +766,13 @@ mod arguments {
767766 output_density_map_points_file : Option < PathBuf > ,
768767 output_density_map_grid_file : Option < PathBuf > ,
769768 output_octree_file : Option < PathBuf > ,
770- compute_normals : bool ,
771- sph_normals : bool ,
772- attributes : Vec < String > ,
773769 ) -> Self {
774770 ReconstructionRunnerPaths {
775771 input_file,
776772 output_file,
777773 output_density_map_points_file,
778774 output_density_map_grid_file,
779775 output_octree_file,
780- compute_normals,
781- sph_normals,
782- attributes,
783776 }
784777 }
785778 }
@@ -796,7 +789,7 @@ pub(crate) fn reconstruction_pipeline(
796789 paths,
797790 & args. params ,
798791 & args. io_params ,
799- args. check_mesh ,
792+ & args. postprocessing ,
800793 ) ?;
801794 } else {
802795 info ! ( "Using single precision (f32) for surface reconstruction." ) ;
@@ -806,7 +799,7 @@ pub(crate) fn reconstruction_pipeline(
806799 "Unable to convert surface reconstruction parameters from f64 to f32."
807800 ) ) ?,
808801 & args. io_params ,
809- args. check_mesh ,
802+ & args. postprocessing ,
810803 ) ?;
811804 }
812805
@@ -818,14 +811,14 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
818811 paths : & ReconstructionRunnerPaths ,
819812 params : & splashsurf_lib:: Parameters < R > ,
820813 io_params : & io:: FormatParameters ,
821- check_mesh : bool ,
814+ postprocessing : & ReconstructionRunnerPostprocessingArgs ,
822815) -> Result < ( ) , anyhow:: Error > {
823816 profile ! ( "surface reconstruction" ) ;
824817
825818 // Load particle positions and attributes to interpolate
826819 let ( particle_positions, attributes) = io:: read_particle_positions_with_attributes (
827820 & paths. input_file ,
828- & paths . attributes ,
821+ & postprocessing . interpolate_attributes ,
829822 & io_params. input ,
830823 )
831824 . with_context ( || {
@@ -843,7 +836,7 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
843836 let mesh = reconstruction. mesh ( ) ;
844837
845838 // Add normals to mesh if requested
846- let mesh = if paths . compute_normals || !attributes. is_empty ( ) {
839+ let mesh = if postprocessing . compute_normals || !attributes. is_empty ( ) {
847840 profile ! ( "compute normals" ) ;
848841
849842 info ! (
@@ -876,8 +869,8 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
876869 let mut mesh_with_data = MeshWithData :: new ( mesh. clone ( ) ) ;
877870
878871 // Compute normals if requested
879- if paths . compute_normals {
880- let normals = if paths . sph_normals {
872+ if postprocessing . compute_normals {
873+ let normals = if postprocessing . sph_normals {
881874 info ! ( "Using SPH interpolation to compute surface normals" ) ;
882875
883876 let sph_normals = interpolator. interpolate_normals ( mesh. vertices ( ) ) ;
@@ -1028,7 +1021,7 @@ pub(crate) fn reconstruction_pipeline_generic<I: Index, R: Real>(
10281021 info ! ( "Done." ) ;
10291022 }
10301023
1031- if check_mesh {
1024+ if postprocessing . check_mesh {
10321025 if let Err ( err) = splashsurf_lib:: marching_cubes:: check_mesh_consistency ( grid, & mesh. mesh ) {
10331026 return Err ( anyhow ! ( "{}" , err) ) ;
10341027 } else {
0 commit comments