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