conspire/geometry/segmentation/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::{
5 geometry::{Coordinate, grid::Grid},
6 math::Quantity,
7};
8use std::{
9 array::from_fn,
10 ops::{Deref, DerefMut, Range},
11};
12
13pub type Segmentation2D<T> = Segmentation<2, T>;
14pub type Segmentation3D<T> = Segmentation<3, T>;
15
16pub struct Segmentation<const D: usize, T> {
17 grid: Grid<D, T>,
18 scale: Coordinate<D>,
19 translate: Coordinate<D>,
20}
21
22impl<const D: usize, T> Segmentation<D, T> {
23 pub fn new(grid: Grid<D, T>, scale: Coordinate<D>, translate: Coordinate<D>) -> Self {
24 assert!(
25 (0..D).all(|axis| scale[axis] > Quantity::default()),
26 "scale must be positive in every direction"
27 );
28 Self {
29 grid,
30 scale,
31 translate,
32 }
33 }
34 pub fn grid(&self) -> &Grid<D, T> {
35 &self.grid
36 }
37 pub fn into_parts(self) -> (Grid<D, T>, Coordinate<D>, Coordinate<D>) {
38 (self.grid, self.scale, self.translate)
39 }
40 pub fn scale(&self) -> &Coordinate<D> {
41 &self.scale
42 }
43 pub fn translate(&self) -> &Coordinate<D> {
44 &self.translate
45 }
46}
47
48impl<const D: usize, T: Copy> Segmentation<D, T> {
49 pub fn extract(&self, ranges: [Range<usize>; D]) -> Self {
50 let translate = from_fn::<_, D, _>(|axis| {
51 self.translate[axis] + ranges[axis].start as f64 * self.scale[axis]
52 })
53 .into();
54 Self {
55 grid: self.grid.extract(ranges),
56 scale: self.scale.clone(),
57 translate,
58 }
59 }
60}
61
62impl<const D: usize, T> From<Grid<D, T>> for Segmentation<D, T> {
63 fn from(grid: Grid<D, T>) -> Self {
64 Self {
65 grid,
66 scale: [1.0; D].into(),
67 translate: [0.0; D].into(),
68 }
69 }
70}
71
72impl<const D: usize, T> Deref for Segmentation<D, T> {
73 type Target = Grid<D, T>;
74 fn deref(&self) -> &Self::Target {
75 &self.grid
76 }
77}
78
79impl<const D: usize, T> DerefMut for Segmentation<D, T> {
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.grid
82 }
83}