1#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
4#[repr(u32)]
5pub enum IndexKind {
6 #[default]
7 Default = 0,
8 None = 1,
9 Natural = 2,
10 YStripes = 3,
11}
12
13impl From<tg_geom_sys::tg_index> for IndexKind {
14 fn from(ix: tg_geom_sys::tg_index) -> Self {
15 match ix {
16 tg_geom_sys::tg_index_TG_DEFAULT => IndexKind::Default,
17 tg_geom_sys::tg_index_TG_NONE => IndexKind::None,
18 tg_geom_sys::tg_index_TG_NATURAL => IndexKind::Natural,
19 tg_geom_sys::tg_index_TG_YSTRIPES => IndexKind::YStripes,
20 _ => unreachable!("unknown index kind: {ix}"),
21 }
22 }
23}
24
25impl From<IndexKind> for tg_geom_sys::tg_index {
26 fn from(ix: IndexKind) -> Self {
27 match ix {
28 IndexKind::Default => tg_geom_sys::tg_index_TG_DEFAULT,
29 IndexKind::None => tg_geom_sys::tg_index_TG_NONE,
30 IndexKind::Natural => tg_geom_sys::tg_index_TG_NATURAL,
31 IndexKind::YStripes => tg_geom_sys::tg_index_TG_YSTRIPES,
32 }
33 }
34}
35
36pub fn set_default_index(ix: IndexKind) {
37 unsafe { tg_geom_sys::tg_env_set_index(ix.into()) }
38}
39
40pub fn set_default_index_spread(spread: i32) {
41 unsafe { tg_geom_sys::tg_env_set_index_spread(spread) }
42}
43
44pub fn set_print_fixed_floats(print: bool) {
45 unsafe { tg_geom_sys::tg_env_set_print_fixed_floats(print) }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use crate::{Point, Ring};
52
53 fn p(x: f64, y: f64) -> Point {
54 Point::new(x, y)
55 }
56
57 fn octagon() -> Vec<Point> {
58 vec![
59 p(3.0, 0.0),
60 p(7.0, 0.0),
61 p(10.0, 3.0),
62 p(10.0, 7.0),
63 p(7.0, 10.0),
64 p(3.0, 10.0),
65 p(0.0, 7.0),
66 p(0.0, 3.0),
67 p(3.0, 0.0),
68 ]
69 }
70
71 #[test]
72 fn test_index_kind_variants() {
73 assert_eq!(IndexKind::Default as u32, 0);
74 assert_eq!(IndexKind::None as u32, 1);
75 assert_eq!(IndexKind::Natural as u32, 2);
76 assert_eq!(IndexKind::YStripes as u32, 3);
77 }
78
79 #[test]
80 fn test_index_kind_default() {
81 let ix: IndexKind = Default::default();
82 assert_eq!(ix, IndexKind::Default);
83 }
84
85 #[test]
86 fn test_index_kind_copy() {
87 let ix1 = IndexKind::Natural;
88 let ix2 = ix1;
89 assert_eq!(ix1, ix2);
90 }
91
92 #[test]
93 fn test_index_kind_eq() {
94 assert_eq!(IndexKind::None, IndexKind::None);
95 assert_ne!(IndexKind::None, IndexKind::Natural);
96 }
97
98 #[test]
99 fn test_index_kind_debug() {
100 let debug_str = format!("{:?}", IndexKind::Natural);
101 assert!(debug_str.contains("Natural"));
102 }
103
104 #[test]
105 fn test_index_kind_sys_roundtrip() {
106 let kinds = [
107 IndexKind::Default,
108 IndexKind::None,
109 IndexKind::Natural,
110 IndexKind::YStripes,
111 ];
112 for kind in &kinds {
113 let sys_kind: tg_geom_sys::tg_index = (*kind).into();
114 let back: IndexKind = sys_kind.into();
115 assert_eq!(*kind, back);
116 }
117 }
118
119 #[test]
120 fn test_set_default_index() {
121 set_default_index(IndexKind::Natural);
122 set_default_index(IndexKind::None);
123 set_default_index(IndexKind::YStripes);
124 set_default_index(IndexKind::Default);
125 }
126
127 #[test]
128 fn test_set_default_index_spread() {
129 set_default_index_spread(4);
130 set_default_index_spread(8);
131 set_default_index_spread(16);
132 }
133
134 #[test]
135 fn test_set_print_fixed_floats() {
136 set_print_fixed_floats(true);
137 set_print_fixed_floats(false);
138 }
139
140 #[test]
141 fn test_ring_index_kinds() {
142 let points = octagon();
143
144 let ring_default = Ring::new(&points).unwrap();
145 let ring_none = Ring::new_ix(&points, IndexKind::None).unwrap();
146 let ring_natural = Ring::new_ix(&points, IndexKind::Natural).unwrap();
147 let ring_ystripes = Ring::new_ix(&points, IndexKind::YStripes).unwrap();
148
149 assert_eq!(ring_default.num_points(), ring_none.num_points());
150 assert_eq!(ring_default.num_points(), ring_natural.num_points());
151 assert_eq!(ring_default.num_points(), ring_ystripes.num_points());
152
153 assert_eq!(ring_default.area(), ring_none.area());
154 assert_eq!(ring_default.area(), ring_natural.area());
155 assert_eq!(ring_default.area(), ring_ystripes.area());
156 }
157
158 #[test]
159 fn test_ring_index_properties() {
160 let ring_natural = Ring::new_ix(&octagon(), IndexKind::Natural).unwrap();
161
162 let spread = ring_natural.index_spread();
163 let num_levels = ring_natural.index_num_levels();
164
165 assert!(spread >= 0);
166 assert!(num_levels >= 0);
167
168 if num_levels > 0 {
169 let level0_rects = ring_natural.index_level_num_rects(0);
170 assert!(level0_rects >= 0);
171 }
172 }
173
174 #[test]
175 fn test_ring_none_index() {
176 let ring_none = Ring::new_ix(&octagon(), IndexKind::None).unwrap();
177 assert_eq!(ring_none.index_num_levels(), 0);
178 }
179}