@@ -30,12 +30,9 @@ static ARGS_OTHER: &str = "Remaining options";
3030#[ clap( group = clap:: ArgGroup :: new( "input" ) . required( true ) ) ]
3131#[ command( next_help_heading = ARGS_OTHER ) ]
3232pub struct ReconstructSubcommandArgs {
33- /// Path to the input file where the particle positions are stored (supported formats: VTK 4.2, VTU, binary f32 XYZ, PLY, BGEO)
34- #[ arg( help_heading = ARGS_IO , short = 'i' , long, group = "input" , value_parser = value_parser!( PathBuf ) ) ]
35- pub input_file : Option < PathBuf > ,
36- /// Path to a sequence of particle files that should be processed, use "{}" in the filename to indicate a placeholder. To specify an output format, use e.g. --output_file="filename_{}.obj".
37- #[ arg( help_heading = ARGS_IO , short = 's' , long, group = "input" , value_parser = value_parser!( PathBuf ) ) ]
38- pub input_sequence : Option < PathBuf > ,
33+ /// Path to the input file where the particle positions are stored (supported formats: VTK 4.2, VTU, binary f32 XYZ, PLY, BGEO), use "{}" in the filename to indicate a placeholder for a sequence.
34+ #[ arg( help_heading = ARGS_IO , group = "input" , value_parser = value_parser!( PathBuf ) ) ]
35+ pub input_file_or_sequence : PathBuf ,
3936 /// Filename for writing the reconstructed surface to disk (default: "{original_filename}_surface.vtk")
4037 #[ arg( help_heading = ARGS_IO , short = 'o' , long, value_parser = value_parser!( PathBuf ) ) ]
4138 pub output_file : Option < PathBuf > ,
@@ -630,100 +627,95 @@ mod arguments {
630627 fn try_from ( args : & ReconstructSubcommandArgs ) -> Result < Self , Self :: Error > {
631628 let output_suffix = "surface" ;
632629
633- if let Some ( input_file ) = & args . input_file {
634- if input_file . is_file ( ) {
635- // Use the user defined output file name if provided...
636- let output_file = if let Some ( output_file ) = & args . output_file {
637- output_file . clone ( )
638- // ...otherwise, generate one based on the input filename
639- } else {
640- let input_stem = input_file . file_stem ( ) . unwrap ( ) . to_string_lossy ( ) ;
641- format ! ( "{}_{}.vtk" , input_stem , output_suffix ) . into ( )
642- } ;
630+ // Make sure that the input path ends with a filename (and not with a path separator)
631+ let input_filename = match args . input_file_or_sequence . file_name ( ) {
632+ Some ( input_filename ) => input_filename . to_string_lossy ( ) ,
633+ None => {
634+ return Err ( anyhow ! (
635+ "The input file path \" {} \" does not end with a filename" ,
636+ args . input_file_or_sequence . display ( )
637+ ) )
638+ }
639+ } ;
643640
644- Self :: try_new (
645- false ,
646- input_file. clone ( ) ,
647- args. output_dir . clone ( ) ,
648- output_file,
649- args. output_dm_points . clone ( ) ,
650- args. output_dm_grid . clone ( ) ,
651- args. output_octree . clone ( ) ,
652- ( args. start_index , args. end_index ) ,
653- args. normals . into_bool ( ) ,
654- args. sph_normals . into_bool ( ) ,
655- args. interpolate_attributes . clone ( ) ,
656- )
657- } else {
641+ // Make sure that the parent directory of the input path exists
642+ if let Some ( input_dir) = args. input_file_or_sequence . parent ( ) {
643+ if !input_dir. is_dir ( ) && input_dir != Path :: new ( "" ) {
658644 return Err ( anyhow ! (
659- "Input file does not exist: \" {}\" " ,
660- input_file. display( )
645+ "The parent directory \" {}\" of the input file path \" {}\" does not exist" ,
646+ input_dir. display( ) ,
647+ args. input_file_or_sequence. display( )
661648 ) ) ;
662649 }
663- } else if let Some ( input_pattern) = & args. input_sequence {
664- // Make sure that the sequence pattern ends with a filename (and not with a path separator)
665- let input_filename = match input_pattern. file_name ( ) {
666- Some ( input_filename) => input_filename. to_string_lossy ( ) ,
667- None => {
668- return Err ( anyhow ! (
669- "The input file path \" {}\" does not end with a filename" ,
670- input_pattern. display( )
671- ) )
672- }
673- } ;
650+ }
651+
652+ let is_sequence: bool ;
653+ let output_filename: PathBuf ;
654+
655+ // Detect sequence pattern or existing input file
656+ if input_filename. contains ( "{}" ) {
657+ is_sequence = true ;
674658
675- // Make sure that the parent directory of the sequence pattern exists
676- if let Some ( input_dir) = input_pattern. parent ( ) {
677- if !input_dir. is_dir ( ) && input_dir != Path :: new ( "" ) {
659+ output_filename = if let Some ( output_file) = & args. output_file {
660+ let output_pattern = output_file. to_string_lossy ( ) ;
661+ if output_pattern. contains ( "{}" ) {
662+ output_pattern. to_string ( ) . into ( )
663+ } else {
678664 return Err ( anyhow ! (
679- "The parent directory \" {}\" of the input file path \" {}\" does not exist" ,
680- input_dir. display( ) ,
681- input_pattern. display( )
665+ "The output filename \" {}\" does not contain a place holder \" {{}}\" " ,
666+ output_file. display( )
682667 ) ) ;
683668 }
684- }
669+ } else {
670+ let input_stem = args
671+ . input_file_or_sequence
672+ . file_stem ( )
673+ . unwrap ( )
674+ . to_string_lossy ( ) ;
675+ // Use VTK format as default fallback
676+ format ! (
677+ "{}.vtk" ,
678+ input_stem. replace( "{}" , & format!( "{}_{{}}" , output_suffix) )
679+ ) . into ( )
680+ } ;
681+ } else {
682+ is_sequence = false ;
685683
686- // Make sure that we have a placeholder "{}" in the filename part of the sequence pattern
687- if input_filename. contains ( "{}" ) {
688- let output_filename = if let Some ( output_file) = & args. output_file {
689- let output_pattern = output_file. to_string_lossy ( ) ;
690- if output_pattern. contains ( "{}" ) {
691- output_pattern. to_string ( )
692- } else {
693- return Err ( anyhow ! ( "The output filename \" {}\" does not contain a place holder \" {{}}\" " , output_file. display( ) ) ) ;
694- }
684+ // Make sure that the input file actually exists
685+ if args. input_file_or_sequence . is_file ( ) {
686+ // Use the user defined output file name if provided...
687+ output_filename = if let Some ( output_file) = & args. output_file {
688+ output_file. clone ( )
689+ // ...otherwise, generate one based on the input filename
695690 } else {
696- let input_stem = input_pattern . file_stem ( ) . unwrap ( ) . to_string_lossy ( ) ;
697- // Use VTK format as default fallback
698- format ! (
699- "{}.vtk" ,
700- input_stem . replace ( "{}" , & format! ( "{}_{{}}" , output_suffix ) )
701- )
691+ let input_stem = args
692+ . input_file_or_sequence
693+ . file_stem ( )
694+ . unwrap ( )
695+ . to_string_lossy ( ) ;
696+ format ! ( "{}_{}.vtk" , input_stem , output_suffix ) . into ( )
702697 } ;
703-
704- Self :: try_new (
705- true ,
706- input_pattern. clone ( ) ,
707- args. output_dir . clone ( ) ,
708- output_filename. into ( ) ,
709- args. output_dm_points . clone ( ) ,
710- args. output_dm_grid . clone ( ) ,
711- args. output_octree . clone ( ) ,
712- ( args. start_index , args. end_index ) ,
713- args. normals . into_bool ( ) ,
714- args. sph_normals . into_bool ( ) ,
715- args. interpolate_attributes . clone ( ) ,
716- )
717698 } else {
718699 return Err ( anyhow ! (
719- "The input sequence pattern \" {}\" does not contain a place holder \" {{}}\" " , input_pattern. display( )
700+ "Input file does not exist: \" {}\" " ,
701+ args. input_file_or_sequence. display( )
720702 ) ) ;
721703 }
722- } else {
723- return Err ( anyhow ! (
724- "Neither an input file path or input sequence pattern was provided"
725- ) ) ;
726704 }
705+
706+ Self :: try_new (
707+ is_sequence,
708+ args. input_file_or_sequence . clone ( ) ,
709+ args. output_dir . clone ( ) ,
710+ output_filename,
711+ args. output_dm_points . clone ( ) ,
712+ args. output_dm_grid . clone ( ) ,
713+ args. output_octree . clone ( ) ,
714+ ( args. start_index , args. end_index ) ,
715+ args. normals . into_bool ( ) ,
716+ args. sph_normals . into_bool ( ) ,
717+ args. interpolate_attributes . clone ( ) ,
718+ )
727719 }
728720 }
729721
0 commit comments