mesh_sieve/algs/
transform.rs1use crate::data::section::Section;
4use crate::data::storage::Storage;
5use crate::io::MeshData;
6use crate::mesh_error::MeshSieveError;
7use crate::topology::cell_type::CellType;
8use crate::topology::point::PointId;
9use crate::topology::sieve::Sieve;
10
11pub enum CoordinateTransform<'a, St>
13where
14 St: Storage<f64>,
15{
16 Function(&'a mut dyn FnMut(PointId, &mut [f64]) -> Result<(), MeshSieveError>),
21 Displacement(&'a Section<f64, St>),
25}
26
27pub struct TransformHooks<'a, M, St, CtSt>
29where
30 St: Storage<f64>,
31 CtSt: Storage<CellType>,
32{
33 pub after_update:
35 Option<&'a mut dyn FnMut(&MeshData<M, f64, St, CtSt>) -> Result<(), MeshSieveError>>,
36}
37
38pub fn transform_mesh<M, St, CtSt>(
40 mesh: &mut MeshData<M, f64, St, CtSt>,
41 transform: CoordinateTransform<'_, St>,
42 mut hooks: TransformHooks<'_, M, St, CtSt>,
43) -> Result<(), MeshSieveError>
44where
45 M: Sieve<Point = PointId>,
46 St: Storage<f64>,
47 CtSt: Storage<CellType>,
48{
49 let coords = mesh
50 .coordinates
51 .as_mut()
52 .ok_or_else(|| MeshSieveError::InvalidGeometry("mesh is missing coordinates".into()))?;
53 let dim = coords.dimension();
54 let points: Vec<PointId> = coords.section().atlas().points().collect();
55
56 match transform {
57 CoordinateTransform::Function(update) => {
58 for point in points {
59 let slice = coords.try_restrict_mut(point)?;
60 if slice.len() != dim {
61 return Err(MeshSieveError::SliceLengthMismatch {
62 point,
63 expected: dim,
64 found: slice.len(),
65 });
66 }
67 update(point, slice)?;
68 }
69 }
70 CoordinateTransform::Displacement(displacement) => {
71 for point in points {
72 let disp = displacement.try_restrict(point)?;
73 if disp.len() != dim {
74 return Err(MeshSieveError::SliceLengthMismatch {
75 point,
76 expected: dim,
77 found: disp.len(),
78 });
79 }
80 let slice = coords.try_restrict_mut(point)?;
81 if slice.len() != dim {
82 return Err(MeshSieveError::SliceLengthMismatch {
83 point,
84 expected: dim,
85 found: slice.len(),
86 });
87 }
88 for (coord, delta) in slice.iter_mut().zip(disp.iter()) {
89 *coord += *delta;
90 }
91 }
92 }
93 }
94
95 if let Some(after_update) = hooks.after_update.as_mut() {
96 after_update(mesh)?;
97 }
98
99 Ok(())
100}