geo/algorithm/relate/geomgraph/
topology_position.rs1use super::{CoordPos, Direction};
2
3use std::fmt;
4
5#[derive(Copy, Clone, PartialEq)]
18pub(crate) enum TopologyPosition {
19 Area {
20 on: Option<CoordPos>,
21 left: Option<CoordPos>,
22 right: Option<CoordPos>,
23 },
24 LineOrPoint {
25 on: Option<CoordPos>,
26 },
27}
28
29impl fmt::Debug for TopologyPosition {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 fn fmt_position(position: &Option<CoordPos>, f: &mut fmt::Formatter) -> fmt::Result {
32 match position {
33 Some(CoordPos::Inside) => write!(f, "i"),
34 Some(CoordPos::OnBoundary) => write!(f, "b"),
35 Some(CoordPos::Outside) => write!(f, "e"),
36 None => write!(f, "_"),
37 }
38 }
39 match self {
40 Self::LineOrPoint { on } => fmt_position(on, f)?,
41 Self::Area { on, left, right } => {
42 fmt_position(left, f)?;
43 fmt_position(on, f)?;
44 fmt_position(right, f)?;
45 }
46 }
47 Ok(())
48 }
49}
50
51impl TopologyPosition {
52 pub fn area(on: CoordPos, left: CoordPos, right: CoordPos) -> Self {
53 Self::Area {
54 on: Some(on),
55 left: Some(left),
56 right: Some(right),
57 }
58 }
59
60 pub fn empty_area() -> Self {
61 Self::Area {
62 on: None,
63 left: None,
64 right: None,
65 }
66 }
67
68 pub fn line_or_point(on: CoordPos) -> Self {
69 Self::LineOrPoint { on: Some(on) }
70 }
71
72 pub fn empty_line_or_point() -> Self {
73 Self::LineOrPoint { on: None }
74 }
75
76 pub fn get(&self, direction: Direction) -> Option<CoordPos> {
77 match (direction, self) {
78 (Direction::Left, Self::Area { left, .. }) => *left,
79 (Direction::Right, Self::Area { right, .. }) => *right,
80 (Direction::On, Self::LineOrPoint { on }) | (Direction::On, Self::Area { on, .. }) => {
81 *on
82 }
83 (_, Self::LineOrPoint { .. }) => {
84 panic!("LineOrPoint only has a position for `Direction::On`")
85 }
86 }
87 }
88
89 pub fn is_empty(&self) -> bool {
90 matches!(
91 self,
92 Self::LineOrPoint { on: None }
93 | Self::Area {
94 on: None,
95 left: None,
96 right: None,
97 }
98 )
99 }
100
101 pub fn is_any_empty(&self) -> bool {
102 !matches!(
103 self,
104 Self::LineOrPoint { on: Some(_) }
105 | Self::Area {
106 on: Some(_),
107 left: Some(_),
108 right: Some(_),
109 }
110 )
111 }
112
113 pub fn is_area(&self) -> bool {
114 matches!(self, Self::Area { .. })
115 }
116
117 pub fn is_line(&self) -> bool {
118 matches!(self, Self::LineOrPoint { .. })
119 }
120
121 pub fn flip(&mut self) {
122 match self {
123 Self::LineOrPoint { .. } => {}
124 Self::Area { left, right, .. } => {
125 std::mem::swap(left, right);
126 }
127 }
128 }
129
130 pub fn set_all_positions(&mut self, position: CoordPos) {
131 match self {
132 Self::LineOrPoint { on } => {
133 *on = Some(position);
134 }
135 Self::Area { on, left, right } => {
136 *on = Some(position);
137 *left = Some(position);
138 *right = Some(position);
139 }
140 }
141 }
142
143 pub fn set_all_positions_if_empty(&mut self, position: CoordPos) {
144 match self {
145 Self::LineOrPoint { on } => {
146 if on.is_none() {
147 *on = Some(position);
148 }
149 }
150 Self::Area { on, left, right } => {
151 if on.is_none() {
152 *on = Some(position);
153 }
154 if left.is_none() {
155 *left = Some(position);
156 }
157 if right.is_none() {
158 *right = Some(position);
159 }
160 }
161 }
162 }
163
164 pub fn set_position(&mut self, direction: Direction, position: CoordPos) {
165 match (direction, self) {
166 (Direction::On, Self::LineOrPoint { on }) => *on = Some(position),
167 (_, Self::LineOrPoint { .. }) => {
168 panic!("invalid assignment dimensions for Self::Line")
169 }
170 (Direction::On, Self::Area { on, .. }) => *on = Some(position),
171 (Direction::Left, Self::Area { left, .. }) => *left = Some(position),
172 (Direction::Right, Self::Area { right, .. }) => *right = Some(position),
173 }
174 }
175
176 pub fn set_on_position(&mut self, position: CoordPos) {
177 match self {
178 Self::LineOrPoint { on } | Self::Area { on, .. } => {
179 *on = Some(position);
180 }
181 }
182 }
183
184 pub fn set_locations(&mut self, new_on: CoordPos, new_left: CoordPos, new_right: CoordPos) {
185 match self {
186 Self::LineOrPoint { .. } => {
187 error!("invalid assignment dimensions for {self:?}");
188 debug_assert!(false, "invalid assignment dimensions for {self:?}");
189 }
190 Self::Area { on, left, right } => {
191 *on = Some(new_on);
192 *left = Some(new_left);
193 *right = Some(new_right);
194 }
195 }
196 }
197}