Skip to content

Commit 64fc72e

Browse files
Merge branch 'yaramo2' into operations
2 parents 8f45cd1 + d6f471e commit 64fc72e

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

test/node_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from itertools import product
22

3+
from pytest import raises
4+
5+
from yaramo.geo_node import Wgs84GeoNode
36
from yaramo.model import Node
47

58
from .helper import create_edge, create_node
@@ -134,3 +137,17 @@ def test_anschluss():
134137
assert switch.connected_on_right == right, (
135138
"right node " f"{coords_str(switch.connected_on_right)} incorrect"
136139
)
140+
141+
142+
def test_implausible_anschluss():
143+
"""Assert that detection of "Anschluss" (head, left, right) raises
144+
an exception on really implausible geographies."""
145+
head = create_node(0, 0) # layout:
146+
point = create_node(2, 2) # l
147+
left = create_node(1, 3) # s r
148+
right = create_node(3, 2) # h
149+
150+
point.connected_nodes.extend((head, left, right))
151+
152+
with raises(Exception) as exception:
153+
point.calc_anschluss_of_all_nodes()

yaramo/node.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,37 +155,42 @@ def get_anschluss_for_edge(self, edge: "Edge") -> EdgeConnectionDirection:
155155
def calc_anschluss_of_all_edges(self):
156156
"""Calculates and sets the 'Anschluss' or connection side of
157157
the connected_nodes based on their geo location."""
158-
159158
if len(self.connected_edges) == 1:
160159
self.connected_edge_on_head = self.connected_edges[0]
161160
return
161+
almost_zero = sys.float_info.epsilon
162162

163-
def get_arc_between_geo_nodes(geo_node_a: "GeoNode", geo_node_b: "GeoNode") -> float:
163+
def get_rad_between_nodes(geo_node_a: GeoNode, geo_node_b: GeoNode) -> float:
164164
"""
165165
Returns the angle of an (maybe imaginary) line between
166-
:param:`node_a` and :param:`node_b`.
166+
:param:`geo_node_a` and :param:`geo_node_b`.
167167
"""
168168
return atan2(geo_node_b.y - geo_node_a.y, geo_node_b.x - geo_node_a.x)
169169

170170
# Determine which node is head, left, and right by trying the
171171
# permutations and checking for plausibility.
172172
for head, left, right in permutations(self.connected_edges):
173173

174-
head_angle_abs = get_arc_between_geo_nodes(head.get_next_geo_node(self), self.geo_node)
175-
left_angle_abs = get_arc_between_geo_nodes(self.geo_node, left.get_next_geo_node(self))
174+
head_angle_abs = get_rad_between_nodes(head.get_next_geo_node(self), self.geo_node)
175+
left_angle_abs = get_rad_between_nodes(self.geo_node, left.get_next_geo_node(self))
176176
left_angle_rel = left_angle_abs - head_angle_abs
177-
if cos(left_angle_rel) <= sys.float_info.epsilon:
177+
if cos(left_angle_rel) <= almost_zero:
178178
# left turn more than (or almost) 90°
179179
continue
180180

181-
right_angle_abs = get_arc_between_geo_nodes(
182-
self.geo_node, right.get_next_geo_node(self)
183-
)
181+
right_angle_abs = get_rad_between_nodes(self.geo_node, right.get_next_geo_node(self))
184182
right_angle_rel = right_angle_abs - head_angle_abs
185-
if cos(right_angle_rel) <= sys.float_info.epsilon:
186-
# left turn more than (or almost) 90°
183+
if cos(right_angle_rel) <= almost_zero:
184+
# right turn more than (or almost) 90°
187185
continue
188186

187+
if cos(left_angle_abs - right_angle_abs) <= almost_zero:
188+
# turn from left to right less than (or almost) 90°
189+
raise Exception(
190+
f"Node {self} has three connected nodes but "
191+
"geometrically, it does not look like a switch."
192+
)
193+
189194
if sin(left_angle_rel) < sin(right_angle_rel):
190195
# Left and right mixed up. Although the permutations do
191196
# contain the correct combination, fixing this right

0 commit comments

Comments
 (0)