Skip to main content

kasane_logic/spatial_id/flex_id/
mod.rs

1pub mod constructor;
2pub mod convert;
3pub mod impls;
4pub mod ops;
5
6use crate::{MAX_ZOOM_LEVEL, Side, TemporalId};
7
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
10#[derive(Clone, PartialEq, Debug, Eq, PartialOrd, Ord, Hash)]
11///拡張空間ID
12pub struct FlexId {
13    f_zoomlevel: u8,
14    f_index: i32,
15    x_zoomlevel: u8,
16    x_index: u32,
17    y_zoomlevel: u8,
18    y_index: u32,
19    temporal_id: TemporalId,
20}
21
22impl FlexId {
23    pub const UPPER_MAX: FlexId = FlexId {
24        f_zoomlevel: 0,
25        f_index: 0,
26        x_zoomlevel: 0,
27        x_index: 0,
28        y_zoomlevel: 0,
29        y_index: 0,
30        temporal_id: TemporalId::WHOLE,
31    };
32
33    pub const LOWER_MAX: FlexId = FlexId {
34        f_zoomlevel: 0,
35        f_index: -1,
36        x_zoomlevel: 0,
37        x_index: 0,
38        y_zoomlevel: 0,
39        y_index: 0,
40        temporal_id: TemporalId::WHOLE,
41    };
42
43    pub fn f_zoomlevel(&self) -> u8 {
44        self.f_zoomlevel
45    }
46    pub fn x_zoomlevel(&self) -> u8 {
47        self.x_zoomlevel
48    }
49    pub fn y_zoomlevel(&self) -> u8 {
50        self.y_zoomlevel
51    }
52    pub fn f_index(&self) -> i32 {
53        self.f_index
54    }
55    pub fn x_index(&self) -> u32 {
56        self.x_index
57    }
58    pub fn y_index(&self) -> u32 {
59        self.y_index
60    }
61
62    ///F方向で二つに切り分ける
63    pub fn f_split(&self, side: Side) -> Option<FlexId> {
64        if self.f_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
65            return None;
66        } else {
67            #[cfg(feature = "temporal_id")]
68            return Some(unsafe {
69                FlexId::new_with_temporal_unchecked(
70                    self.f_zoomlevel() + 1,
71                    self.f_index() * 2 + side as i32,
72                    self.x_zoomlevel(),
73                    self.x_index(),
74                    self.y_zoomlevel(),
75                    self.y_index(),
76                    self.temporal_id.clone(),
77                )
78            });
79
80            #[cfg(not(feature = "temporal_id"))]
81            return Some(unsafe {
82                FlexId::new_unchecked(
83                    self.f_zoomlevel() + 1,
84                    self.f_index() * 2 + side as i32,
85                    self.x_zoomlevel(),
86                    self.x_index(),
87                    self.y_zoomlevel(),
88                    self.y_index(),
89                )
90            });
91        }
92    }
93
94    ///X方向で二つに切り分ける
95    pub fn x_split(&self, side: Side) -> Option<FlexId> {
96        if self.x_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
97            return None;
98        } else {
99            #[cfg(feature = "temporal_id")]
100            return Some(unsafe {
101                FlexId::new_with_temporal_unchecked(
102                    self.f_zoomlevel(),
103                    self.f_index(),
104                    self.x_zoomlevel() + 1,
105                    self.x_index() * 2 + side as u32,
106                    self.y_zoomlevel(),
107                    self.y_index(),
108                    self.temporal().clone(),
109                )
110            });
111
112            #[cfg(not(feature = "temporal_id"))]
113            return Some(unsafe {
114                FlexId::new_unchecked(
115                    self.f_zoomlevel(),
116                    self.f_index(),
117                    self.x_zoomlevel() + 1,
118                    self.x_index() * 2 + side as u32,
119                    self.y_zoomlevel(),
120                    self.y_index(),
121                )
122            });
123        }
124    }
125
126    ///Y方向で二つに切り分ける
127    pub fn y_split(&self, side: Side) -> Option<FlexId> {
128        if self.y_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
129            return None;
130        } else {
131            #[cfg(feature = "temporal_id")]
132            return Some(unsafe {
133                FlexId::new_with_temporal_unchecked(
134                    self.f_zoomlevel(),
135                    self.f_index(),
136                    self.x_zoomlevel(),
137                    self.x_index(),
138                    self.y_zoomlevel() + 1,
139                    self.y_index() * 2 + side as u32,
140                    self.temporal_id.clone(),
141                )
142            });
143
144            #[cfg(not(feature = "temporal_id"))]
145            return Some(unsafe {
146                FlexId::new_unchecked(
147                    self.f_zoomlevel(),
148                    self.f_index(),
149                    self.x_zoomlevel(),
150                    self.x_index(),
151                    self.y_zoomlevel() + 1,
152                    self.y_index() * 2 + side as u32,
153                )
154            });
155        }
156    }
157}