|
1 | | -use anyhow::{anyhow, Context}; |
2 | | -use coarse_prof::profile; |
3 | | -use log::info; |
4 | | -use splashsurf_lib::mesh::PointCloud3d; |
5 | | -use splashsurf_lib::{density_map, Index, Real}; |
6 | | - |
7 | | -use crate::io; |
8 | | -use crate::{ReconstructionRunnerArgs, ReconstructionRunnerPaths}; |
9 | | - |
10 | | -// TODO: Detect smallest index type (i.e. check if ok to use i32/u32 as index) |
11 | | - |
12 | | -pub(crate) fn entry_point_f64( |
13 | | - paths: &ReconstructionRunnerPaths, |
14 | | - args: &ReconstructionRunnerArgs, |
15 | | -) -> Result<(), anyhow::Error> { |
16 | | - if args.use_double_precision { |
17 | | - type I = i64; |
18 | | - type R = f64; |
19 | | - |
20 | | - entry_point_generic::<I, R>(paths, &args.params)?; |
21 | | - } else { |
22 | | - type I = i64; |
23 | | - type R = f32; |
24 | | - |
25 | | - entry_point_generic::<I, R>( |
26 | | - paths, |
27 | | - &args.params.try_convert().ok_or(anyhow!( |
28 | | - "Unable to convert surface reconstruction parameters from f64 to f32." |
29 | | - ))?, |
30 | | - )?; |
31 | | - } |
32 | | - |
33 | | - Ok(()) |
34 | | -} |
35 | | - |
36 | | -pub(crate) fn entry_point_generic<I: Index, R: Real>( |
37 | | - paths: &ReconstructionRunnerPaths, |
38 | | - params: &splashsurf_lib::Parameters<R>, |
39 | | -) -> Result<(), anyhow::Error> { |
40 | | - profile!("surface reconstruction cli"); |
41 | | - |
42 | | - info!( |
43 | | - "Loading dataset from \"{}\"...", |
44 | | - paths.input_file.to_string_lossy() |
45 | | - ); |
46 | | - let particle_positions = if let Some(extension) = paths.input_file.extension() { |
47 | | - profile!("loading particle positions"); |
48 | | - let extension = extension.to_string_lossy(); |
49 | | - match extension.to_lowercase().as_str() { |
50 | | - "vtk" => { |
51 | | - let sph_dataset = io::read_vtk(&paths.input_file)?; |
52 | | - io::particles_from_dataset(&sph_dataset)? |
53 | | - } |
54 | | - "xyz" => io::particles_from_xyz(&paths.input_file)?, |
55 | | - _ => { |
56 | | - return Err(anyhow!( |
57 | | - "Unsupported file format extension '{}' of input file '{}'", |
58 | | - extension, |
59 | | - paths.input_file.to_string_lossy() |
60 | | - )); |
61 | | - } |
62 | | - } |
63 | | - } else { |
64 | | - return Err(anyhow!( |
65 | | - "Unable to detect file format of input file '{}'", |
66 | | - paths.input_file.to_string_lossy() |
67 | | - )); |
68 | | - }; |
69 | | - info!( |
70 | | - "Loaded dataset with {} particle positions.", |
71 | | - particle_positions.len() |
72 | | - ); |
73 | | - |
74 | | - let reconstruction = |
75 | | - splashsurf_lib::reconstruct_surface::<I, R>(particle_positions.as_slice(), ¶ms)?; |
76 | | - |
77 | | - let grid = reconstruction.grid(); |
78 | | - let density_map = reconstruction.density_map(); |
79 | | - let mesh = reconstruction.mesh(); |
80 | | - |
81 | | - { |
82 | | - profile!("write surface mesh to file"); |
83 | | - info!( |
84 | | - "Writing surface mesh to \"{}\"...", |
85 | | - paths.output_file.to_string_lossy() |
86 | | - ); |
87 | | - io::write_vtk(mesh, &paths.output_file, "mesh").with_context(|| { |
88 | | - format!( |
89 | | - "Failed to write reconstructed surface to output file '{}'", |
90 | | - paths.output_file.to_string_lossy() |
91 | | - ) |
92 | | - })?; |
93 | | - info!("Done."); |
94 | | - } |
95 | | - |
96 | | - if let Some(output_density_map_points_file) = &paths.output_density_map_points_file { |
97 | | - info!("Constructing density map point cloud..."); |
98 | | - |
99 | | - let point_cloud: PointCloud3d<R> = { |
100 | | - let mut points = Vec::with_capacity(density_map.len()); |
101 | | - for (flat_point_index, _) in density_map.iter() { |
102 | | - let point = grid.try_unflatten_point_index(flat_point_index).unwrap(); |
103 | | - points.push(grid.point_coordinates(&point)); |
104 | | - } |
105 | | - |
106 | | - PointCloud3d { points } |
107 | | - }; |
108 | | - |
109 | | - info!( |
110 | | - "Saving density map point cloud to \"{}\"...", |
111 | | - output_density_map_points_file.to_string_lossy() |
112 | | - ); |
113 | | - |
114 | | - io::write_vtk( |
115 | | - &point_cloud, |
116 | | - output_density_map_points_file, |
117 | | - "density_map_points", |
118 | | - )?; |
119 | | - |
120 | | - info!("Done."); |
121 | | - } |
122 | | - |
123 | | - if let Some(output_density_map_grid_file) = &paths.output_density_map_grid_file { |
124 | | - info!("Constructing density map hex mesh..."); |
125 | | - |
126 | | - let density_mesh = |
127 | | - density_map::sparse_density_map_to_hex_mesh(&density_map, &grid, R::zero()); |
128 | | - |
129 | | - info!( |
130 | | - "Saving density map hex mesh to \"{}\"...", |
131 | | - output_density_map_grid_file.to_string_lossy() |
132 | | - ); |
133 | | - |
134 | | - io::write_vtk( |
135 | | - density_mesh.to_dataset(), |
136 | | - output_density_map_grid_file, |
137 | | - "density_map", |
138 | | - )?; |
139 | | - |
140 | | - info!("Done."); |
141 | | - } |
142 | | - |
143 | | - Ok(()) |
144 | | -} |
| 1 | +use anyhow::{anyhow, Context}; |
| 2 | +use coarse_prof::profile; |
| 3 | +use log::info; |
| 4 | +use splashsurf_lib::mesh::PointCloud3d; |
| 5 | +use splashsurf_lib::{density_map, Index, Real}; |
| 6 | + |
| 7 | +use crate::io; |
| 8 | +use crate::{ReconstructionRunnerArgs, ReconstructionRunnerPaths}; |
| 9 | + |
| 10 | +// TODO: Detect smallest index type (i.e. check if ok to use i32/u32 as index) |
| 11 | + |
| 12 | +pub(crate) fn entry_point_f64( |
| 13 | + paths: &ReconstructionRunnerPaths, |
| 14 | + args: &ReconstructionRunnerArgs, |
| 15 | +) -> Result<(), anyhow::Error> { |
| 16 | + if args.use_double_precision { |
| 17 | + type I = i64; |
| 18 | + type R = f64; |
| 19 | + |
| 20 | + entry_point_generic::<I, R>(paths, &args.params)?; |
| 21 | + } else { |
| 22 | + type I = i64; |
| 23 | + type R = f32; |
| 24 | + |
| 25 | + entry_point_generic::<I, R>( |
| 26 | + paths, |
| 27 | + &args.params.try_convert().ok_or(anyhow!( |
| 28 | + "Unable to convert surface reconstruction parameters from f64 to f32." |
| 29 | + ))?, |
| 30 | + )?; |
| 31 | + } |
| 32 | + |
| 33 | + Ok(()) |
| 34 | +} |
| 35 | + |
| 36 | +pub(crate) fn entry_point_generic<I: Index, R: Real>( |
| 37 | + paths: &ReconstructionRunnerPaths, |
| 38 | + params: &splashsurf_lib::Parameters<R>, |
| 39 | +) -> Result<(), anyhow::Error> { |
| 40 | + profile!("surface reconstruction cli"); |
| 41 | + |
| 42 | + info!( |
| 43 | + "Loading dataset from \"{}\"...", |
| 44 | + paths.input_file.to_string_lossy() |
| 45 | + ); |
| 46 | + let particle_positions = if let Some(extension) = paths.input_file.extension() { |
| 47 | + profile!("loading particle positions"); |
| 48 | + let extension = extension.to_string_lossy(); |
| 49 | + match extension.to_lowercase().as_str() { |
| 50 | + "vtk" => { |
| 51 | + let sph_dataset = io::read_vtk(&paths.input_file)?; |
| 52 | + io::particles_from_dataset(&sph_dataset)? |
| 53 | + } |
| 54 | + "xyz" => io::particles_from_xyz(&paths.input_file)?, |
| 55 | + _ => { |
| 56 | + return Err(anyhow!( |
| 57 | + "Unsupported file format extension '{}' of input file '{}'", |
| 58 | + extension, |
| 59 | + paths.input_file.to_string_lossy() |
| 60 | + )); |
| 61 | + } |
| 62 | + } |
| 63 | + } else { |
| 64 | + return Err(anyhow!( |
| 65 | + "Unable to detect file format of input file '{}'", |
| 66 | + paths.input_file.to_string_lossy() |
| 67 | + )); |
| 68 | + }; |
| 69 | + info!( |
| 70 | + "Loaded dataset with {} particle positions.", |
| 71 | + particle_positions.len() |
| 72 | + ); |
| 73 | + |
| 74 | + let reconstruction = |
| 75 | + splashsurf_lib::reconstruct_surface::<I, R>(particle_positions.as_slice(), ¶ms)?; |
| 76 | + |
| 77 | + let grid = reconstruction.grid(); |
| 78 | + let density_map = reconstruction.density_map(); |
| 79 | + let mesh = reconstruction.mesh(); |
| 80 | + |
| 81 | + { |
| 82 | + profile!("write surface mesh to file"); |
| 83 | + info!( |
| 84 | + "Writing surface mesh to \"{}\"...", |
| 85 | + paths.output_file.to_string_lossy() |
| 86 | + ); |
| 87 | + io::write_vtk(mesh, &paths.output_file, "mesh").with_context(|| { |
| 88 | + format!( |
| 89 | + "Failed to write reconstructed surface to output file '{}'", |
| 90 | + paths.output_file.to_string_lossy() |
| 91 | + ) |
| 92 | + })?; |
| 93 | + info!("Done."); |
| 94 | + } |
| 95 | + |
| 96 | + if let Some(output_density_map_points_file) = &paths.output_density_map_points_file { |
| 97 | + info!("Constructing density map point cloud..."); |
| 98 | + |
| 99 | + let point_cloud: PointCloud3d<R> = { |
| 100 | + let mut points = Vec::with_capacity(density_map.len()); |
| 101 | + for (flat_point_index, _) in density_map.iter() { |
| 102 | + let point = grid.try_unflatten_point_index(flat_point_index).unwrap(); |
| 103 | + points.push(grid.point_coordinates(&point)); |
| 104 | + } |
| 105 | + |
| 106 | + PointCloud3d { points } |
| 107 | + }; |
| 108 | + |
| 109 | + info!( |
| 110 | + "Saving density map point cloud to \"{}\"...", |
| 111 | + output_density_map_points_file.to_string_lossy() |
| 112 | + ); |
| 113 | + |
| 114 | + io::write_vtk( |
| 115 | + &point_cloud, |
| 116 | + output_density_map_points_file, |
| 117 | + "density_map_points", |
| 118 | + )?; |
| 119 | + |
| 120 | + info!("Done."); |
| 121 | + } |
| 122 | + |
| 123 | + if let Some(output_density_map_grid_file) = &paths.output_density_map_grid_file { |
| 124 | + info!("Constructing density map hex mesh..."); |
| 125 | + |
| 126 | + let density_mesh = |
| 127 | + density_map::sparse_density_map_to_hex_mesh(&density_map, &grid, R::zero()); |
| 128 | + |
| 129 | + info!( |
| 130 | + "Saving density map hex mesh to \"{}\"...", |
| 131 | + output_density_map_grid_file.to_string_lossy() |
| 132 | + ); |
| 133 | + |
| 134 | + io::write_vtk( |
| 135 | + density_mesh.to_dataset(), |
| 136 | + output_density_map_grid_file, |
| 137 | + "density_map", |
| 138 | + )?; |
| 139 | + |
| 140 | + info!("Done."); |
| 141 | + } |
| 142 | + |
| 143 | + Ok(()) |
| 144 | +} |
0 commit comments