@@ -460,7 +460,7 @@ pub struct ReconstructionPostprocessingParameters {
460460 /// Number of Laplacian smoothing iterations to apply to normals if normal interpolation is enabled
461461 pub normals_smoothing_iters : Option < usize > ,
462462 /// Interpolate point attributes with the given names from the input attributes to the reconstructed surface
463- pub interpolate_attributes : Vec < String > ,
463+ pub interpolate_attributes : Option < Vec < String > > ,
464464 /// Number of Laplacian smoothing iterations to apply t the reconstructed mesh
465465 pub mesh_smoothing_iters : Option < usize > ,
466466 /// Enable feature weights for mesh smoothing if mesh smoothing enabled. Preserves isolated particles even under strong smoothing.
@@ -487,6 +487,38 @@ pub struct ReconstructionPostprocessingParameters {
487487 pub mesh_aabb_clamp_vertices : bool ,
488488}
489489
490+ impl ReconstructionPostprocessingParameters {
491+ /// Returns a new instance of the post-processing parameters with all postprocessing disabled
492+ pub fn new ( ) -> Self {
493+ ReconstructionPostprocessingParameters {
494+ check_mesh_closed : false ,
495+ check_mesh_manifold : false ,
496+ check_mesh_orientation : false ,
497+ check_mesh_debug : false ,
498+ mesh_cleanup : false ,
499+ mesh_cleanup_snap_dist : None ,
500+ decimate_barnacles : false ,
501+ keep_vertices : false ,
502+ compute_normals : false ,
503+ sph_normals : false ,
504+ normals_smoothing_iters : None ,
505+ interpolate_attributes : None ,
506+ mesh_smoothing_iters : None ,
507+ mesh_smoothing_weights : false ,
508+ mesh_smoothing_weights_normalization : 0.0 ,
509+ generate_quads : false ,
510+ quad_max_edge_diag_ratio : 0.0 ,
511+ quad_max_normal_angle : 0.0 ,
512+ quad_max_interior_angle : 0.0 ,
513+ output_mesh_smoothing_weights : false ,
514+ output_raw_normals : false ,
515+ output_raw_mesh : false ,
516+ mesh_aabb : None ,
517+ mesh_aabb_clamp_vertices : false ,
518+ }
519+ }
520+ }
521+
490522/// Conversion and validation of command line arguments
491523pub ( crate ) mod arguments {
492524 use super :: { ReconstructSubcommandArgs , ReconstructionPostprocessingParameters } ;
@@ -619,7 +651,7 @@ pub(crate) mod arguments {
619651 compute_normals : args. normals . into_bool ( ) ,
620652 sph_normals : args. sph_normals . into_bool ( ) ,
621653 normals_smoothing_iters : args. normals_smoothing_iters ,
622- interpolate_attributes : args. interpolate_attributes . clone ( ) ,
654+ interpolate_attributes : Some ( args. interpolate_attributes . clone ( ) ) ,
623655 mesh_smoothing_iters : args. mesh_smoothing_iters ,
624656 mesh_smoothing_weights : args. mesh_smoothing_weights . into_bool ( ) ,
625657 mesh_smoothing_weights_normalization : args. mesh_smoothing_weights_normalization ,
@@ -959,11 +991,15 @@ pub(crate) fn reconstruction_pipeline_from_args(
959991/// Inputs are the particle positions, a (possibly empty) list of attributes defined on the particles,
960992/// [`Parameters`](splashsurf_lib::Parameters) for the surface reconstruction itself, and a set of parameters for optional
961993/// post-processing steps.
962- /// Please note that, unlike the CLI, the parameters for the surface reconstruction are not relative
963- /// to the particle radius but absolute values.
994+ ///
995+ /// * `params`: Please note that, unlike the CLI, any distance parameters for the surface reconstruction are not relative
996+ /// to the particle radius but are **absolute distance values** (see [`Parameters`](splashsurf_lib::Parameters)).
997+ /// * `attributes`: Note that the attributes are not required for the reconstruction itself but can be used for
998+ /// post-processing steps like attribute interpolation to the reconstructed surface. This has to be enabled explicitly
999+ /// in the post-processing parameters (see [`ReconstructionPostprocessingParameters`]).
9641000pub fn reconstruction_pipeline < I : Index , R : Real > (
9651001 particle_positions : & [ Vector3 < R > ] ,
966- attributes : Vec < MeshAttribute < R > > ,
1002+ attributes : & [ MeshAttribute < R > ] ,
9671003 params : & splashsurf_lib:: Parameters < R > ,
9681004 postprocessing : & ReconstructionPostprocessingParameters ,
9691005) -> Result < ReconstructionResult < I , R > , anyhow:: Error > {
@@ -1018,7 +1054,12 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
10181054 // Initialize SPH interpolator if required later
10191055 let interpolator_required = postprocessing. mesh_smoothing_weights
10201056 || postprocessing. sph_normals
1021- || !attributes. is_empty ( ) ;
1057+ || ( !attributes. is_empty ( )
1058+ && !postprocessing
1059+ . interpolate_attributes
1060+ . as_ref ( )
1061+ . map ( Vec :: is_empty)
1062+ . unwrap_or ( true ) ) ;
10221063 let interpolator = if interpolator_required {
10231064 profile ! ( "initialize interpolator" ) ;
10241065 info ! ( "Post-processing: Initializing interpolator..." ) ;
@@ -1235,23 +1276,28 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
12351276 }
12361277
12371278 // Interpolate attributes if requested
1238- if !attributes. is_empty ( ) {
1279+ if let Some ( attribute_names) = & postprocessing. interpolate_attributes
1280+ && !attributes. is_empty ( )
1281+ {
12391282 profile ! ( "interpolate attributes" ) ;
12401283 info ! ( "Post-processing: Interpolating attributes..." ) ;
12411284 let interpolator = interpolator. as_ref ( ) . expect ( "interpolator is required" ) ;
12421285
1243- for attribute in attributes. into_iter ( ) {
1286+ for attribute in attributes
1287+ . iter ( )
1288+ . filter ( |a| attribute_names. contains ( & a. name ) )
1289+ {
12441290 info ! ( "Interpolating attribute \" {}\" ..." , attribute. name) ;
12451291
1246- match attribute. data {
1292+ match & attribute. data {
12471293 AttributeData :: ScalarReal ( values) => {
12481294 let interpolated_values = interpolator. interpolate_scalar_quantity (
12491295 values. as_slice ( ) ,
12501296 mesh_with_data. vertices ( ) ,
12511297 true ,
12521298 ) ;
12531299 mesh_with_data. point_attributes . push ( MeshAttribute :: new (
1254- attribute. name ,
1300+ attribute. name . clone ( ) ,
12551301 AttributeData :: ScalarReal ( interpolated_values) ,
12561302 ) ) ;
12571303 }
@@ -1262,7 +1308,7 @@ pub fn reconstruction_pipeline<I: Index, R: Real>(
12621308 true ,
12631309 ) ;
12641310 mesh_with_data. point_attributes . push ( MeshAttribute :: new (
1265- attribute. name ,
1311+ attribute. name . clone ( ) ,
12661312 AttributeData :: Vector3Real ( interpolated_values) ,
12671313 ) ) ;
12681314 }
@@ -1458,7 +1504,11 @@ pub(crate) fn reconstruction_pipeline_from_path<I: Index, R: Real>(
14581504 // Load particle positions and attributes to interpolate
14591505 let ( particle_positions, attributes) = io:: read_particle_positions_with_attributes (
14601506 & paths. input_file ,
1461- & postprocessing. interpolate_attributes ,
1507+ postprocessing
1508+ . interpolate_attributes
1509+ . as_ref ( )
1510+ . map ( Vec :: as_slice)
1511+ . unwrap_or ( & [ ] ) ,
14621512 & io_params. input ,
14631513 )
14641514 . with_context ( || {
@@ -1472,7 +1522,7 @@ pub(crate) fn reconstruction_pipeline_from_path<I: Index, R: Real>(
14721522 tri_mesh,
14731523 tri_quad_mesh,
14741524 raw_reconstruction : reconstruction,
1475- } = reconstruction_pipeline :: < I , R > ( & particle_positions, attributes, params, postprocessing) ?;
1525+ } = reconstruction_pipeline :: < I , R > ( & particle_positions, & attributes, params, postprocessing) ?;
14761526
14771527 if postprocessing. output_raw_mesh {
14781528 profile ! ( "write surface mesh to file" ) ;
0 commit comments