hexagon_map/isometric/
mod.rs

1use crate::{CubicPoint, HexPoint, Joint, Orientation};
2use std::fmt::{Debug, Formatter};
3
4pub struct IsometricLine {
5    wrapper: IsometricLineSealed,
6}
7
8impl Debug for IsometricLine {
9    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
10        match self {
11            IsometricLine { wrapper: IsometricLineSealed::Zero { center, stop } } => {
12                let index = match stop {
13                    true => 1,
14                    false => 0,
15                };
16                f.debug_struct("IsometricLine").field("current", center).field("distance", &0).field("index", &index).finish()
17            }
18            IsometricLine { wrapper: IsometricLineSealed::Normal { current, distance, index } } => f
19                .debug_struct("IsometricLine")
20                .field("current", &current.target())
21                .field("distance", distance)
22                .field("index", index)
23                .finish(),
24        }
25    }
26}
27
28enum IsometricLineSealed {
29    Zero { center: CubicPoint, stop: bool },
30    Normal { current: Joint, distance: isize, index: isize },
31}
32
33impl IsometricLine {
34    pub fn new<P>(center: P, distance: usize) -> IsometricLine
35    where
36        P: HexPoint,
37    {
38        let center = center.as_cubic_point();
39        let h_offset = distance as isize;
40        let wrapper = match distance {
41            0 => IsometricLineSealed::Zero { center, stop: false },
42            _ => IsometricLineSealed::Normal {
43                current: Joint::new(CubicPoint { p: center.p + h_offset, q: center.q + h_offset - 1 }, Orientation::P(true)),
44                distance: h_offset,
45                index: 0,
46            },
47        };
48        IsometricLine { wrapper }
49    }
50    fn increase(&mut self) {
51        match &mut self.wrapper {
52            IsometricLineSealed::Zero { stop, .. } => {
53                *stop = true;
54            }
55            IsometricLineSealed::Normal { index, .. } => {
56                *index += 1;
57            }
58        }
59    }
60    pub fn is_finish(&self) -> bool {
61        match &self.wrapper {
62            IsometricLineSealed::Zero { stop, .. } => *stop,
63            IsometricLineSealed::Normal { index, distance, .. } => *index >= 6 * *distance,
64        }
65    }
66}
67
68impl Iterator for IsometricLine {
69    type Item = CubicPoint;
70
71    fn next(&mut self) -> Option<Self::Item> {
72        let mut out = None;
73        if !self.is_finish() {
74            match &mut self.wrapper {
75                IsometricLineSealed::Zero { center, .. } => out = Some(*center),
76                IsometricLineSealed::Normal { current, distance, index } => {
77                    match *index % *distance {
78                        0 => {
79                            *current = current.forward().rotate(false);
80                            out = Some(current.source().as_cubic_point());
81                        }
82                        _ => {
83                            *current = current.forward();
84                            out = Some(current.source().as_cubic_point());
85                        }
86                    };
87                }
88            }
89            self.increase();
90        }
91        out
92    }
93}