Skip to main content

qsm_core/
grid.rs

1//! Lightweight 3D volume grid descriptor.
2//!
3//! Contains only the geometric information needed by algorithm kernels:
4//! dimensions and voxel sizes. This eliminates the need to pass 6 separate
5//! parameters (nx, ny, nz, vsx, vsy, vsz) to every function.
6
7/// A 3D volume grid with dimensions and voxel sizes.
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub struct Grid {
10    /// Volume dimensions (nx, ny, nz)
11    pub dims: (usize, usize, usize),
12    /// Voxel sizes in mm (vsx, vsy, vsz)
13    pub voxel_size: (f64, f64, f64),
14}
15
16impl Grid {
17    /// Create a new Grid from dimensions and voxel sizes.
18    #[inline]
19    pub fn new(nx: usize, ny: usize, nz: usize, vsx: f64, vsy: f64, vsz: f64) -> Self {
20        Self {
21            dims: (nx, ny, nz),
22            voxel_size: (vsx, vsy, vsz),
23        }
24    }
25
26    #[inline]
27    pub fn nx(&self) -> usize { self.dims.0 }
28    #[inline]
29    pub fn ny(&self) -> usize { self.dims.1 }
30    #[inline]
31    pub fn nz(&self) -> usize { self.dims.2 }
32    #[inline]
33    pub fn vsx(&self) -> f64 { self.voxel_size.0 }
34    #[inline]
35    pub fn vsy(&self) -> f64 { self.voxel_size.1 }
36    #[inline]
37    pub fn vsz(&self) -> f64 { self.voxel_size.2 }
38
39    /// Total number of voxels.
40    #[inline]
41    pub fn n_total(&self) -> usize {
42        self.dims.0 * self.dims.1 * self.dims.2
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_grid_basic() {
52        let g = Grid::new(64, 64, 32, 1.0, 1.0, 2.0);
53        assert_eq!(g.nx(), 64);
54        assert_eq!(g.ny(), 64);
55        assert_eq!(g.nz(), 32);
56        assert_eq!(g.n_total(), 64 * 64 * 32);
57        assert_eq!(g.vsx(), 1.0);
58        assert_eq!(g.vsz(), 2.0);
59    }
60
61    #[test]
62    fn test_grid_copy() {
63        let g = Grid::new(10, 20, 30, 0.5, 0.5, 1.0);
64        let g2 = g;
65        assert_eq!(g, g2);
66    }
67}