models.rs
3.0 kB · rust · 102 lines
1use super::{Orientation, Projection, FILL, VOID};2use crate::two::Cell2d;3use mrlycore::errors::Result;4use mrlycore::tensor::Tensor;56/// The projected cell: a triangle grid with its projection, orientation and start parity.7#[derive(Clone, Debug, PartialEq, Eq)]8pub struct Cell6d {9 /// The triangle grid of type codes.10 pub cell: Cell2d,11 /// The projection that made the grid.12 pub projection: Projection,13 /// The way the hexagon points.14 pub orientation: Orientation,15 /// The parity of the first triangle.16 pub start: u8,17}1819impl Cell6d {20 /// Builds a cell from its four parts.21 pub fn new(22 cell: Cell2d,23 projection: Projection,24 orientation: Orientation,25 start: u8,26 ) -> Cell6d {27 Cell6d {28 cell,29 projection,30 orientation,31 start,32 }33 }34 /// Returns the grid width in triangles.35 pub fn width(&self) -> usize {36 self.cell.width()37 }38 /// Returns the grid height in triangles.39 pub fn height(&self) -> usize {40 self.cell.height()41 }42 /// Swaps every fill triangle for a void and back.43 pub fn anti(mut self) -> Cell6d {44 for v in self.cell.cell.types.bytes_mut().iter_mut() {45 if *v == FILL {46 *v = VOID;47 } else if *v == VOID {48 *v = FILL;49 }50 }51 self52 }53 /// Maps each triangle to one at or above the threshold, zero below.54 pub fn binarize(self, threshold: u8) -> Cell6d {55 Cell6d {56 cell: self.cell.binarize(threshold),57 ..self58 }59 }60 /// Binarizes the triangles at the threshold Otsu's method picks.61 pub fn binarize_otsu(self) -> Cell6d {62 Cell6d {63 cell: self.cell.binarize_otsu(),64 ..self65 }66 }67 /// Rounds each triangle to the mean of its masked neighborhood, wrapping on request.68 pub fn blur(self, mask: &Tensor, wrap: bool) -> Result<Cell6d> {69 Ok(Cell6d {70 cell: self.cell.blur(mask, wrap)?,71 ..self72 })73 }74 /// Writes the value wherever the tiled mask is nonzero.75 pub fn perforate(self, mask: &Tensor, value: u8) -> Result<Cell6d> {76 Ok(Cell6d {77 cell: self.cell.perforate(mask, value)?,78 ..self79 })80 }81}8283#[cfg(test)]84mod tests {85 use super::*;86 use crate::six::designs::iso_design;87 #[test]88 fn binarize_wrapper_keeps_projection_metadata() {89 let hex = iso_design(23, 3, 1, 2).unwrap();90 let binarized = hex.clone().binarize(1);91 assert_eq!(binarized.projection, hex.projection);92 assert_eq!(binarized.orientation, hex.orientation);93 assert_eq!(binarized.start, hex.start);94 }95 #[test]96 fn perforate_wrapper_zero_mask_is_identity_6d() {97 let hex = iso_design(23, 3, 1, 2).unwrap();98 let mask = Tensor::new(hex.cell.types().shape.clone());99 let perforated = hex.clone().perforate(&mask, 5).unwrap();100 assert_eq!(perforated.cell.types(), hex.cell.types());101 }102}