Skip to content

Commit

Permalink
Removes self-looped (zero-length) edges if encountered in `nX_simple_…
Browse files Browse the repository at this point in the history
…geoms`.
  • Loading branch information
songololo committed May 18, 2021
1 parent 4855df1 commit 33b75f8
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 11 deletions.
10 changes: 9 additions & 1 deletion cityseer/tools/graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,18 @@ def _process_node(n):
return x, y

# unpack coordinates and build simple edge geoms
remove_edges = []
for s, e, k in tqdm(g_multi_copy.edges(keys=True), disable=checks.quiet_mode):
s_x, s_y = _process_node(s)
e_x, e_y = _process_node(e)
g_multi_copy[s][e][k]['geom'] = geometry.LineString([[s_x, s_y], [e_x, e_y]])
g = geometry.LineString([[s_x, s_y], [e_x, e_y]])
if s == e and g.length == 0:
remove_edges.append((s, e, k))
else:
g_multi_copy[s][e][k]['geom'] = g
for s, e, k in remove_edges:
logger.warning(f'Found zero length looped edge for node {s}, removing from graph.')
g_multi_copy.remove_edge(s, e, key=k)

return g_multi_copy

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

setup(
name='cityseer',
version='1.0.4',
version='1.0.5',
packages=['cityseer', 'cityseer.algos', 'cityseer.metrics', 'cityseer.tools'],
description='Computational tools for urban analysis',
url='https://github.com/benchmark-urbanism/cityseer-api',
Expand Down
28 changes: 19 additions & 9 deletions tests/tools/test_graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,36 @@
from cityseer.algos import checks
from cityseer.metrics import networks, layers
from cityseer.tools import mock, graphs
from cityseer.tools.mock import primal_graph, diamond_graph
from cityseer.tools.mock import mock_graph, primal_graph, diamond_graph


def test_nX_simple_geoms(primal_graph):
for s, e, k in primal_graph.edges(keys=True):
def test_nX_simple_geoms():
g_raw = mock_graph()
# primal_graph already has simple geoms added, so use raw mock_graph instead
g_simple = graphs.nX_simple_geoms(g_raw)
for s, e, k in g_simple.edges(keys=True):
line_geom = geometry.LineString([
[primal_graph.nodes[s]['x'], primal_graph.nodes[s]['y']],
[primal_graph.nodes[e]['x'], primal_graph.nodes[e]['y']]
[g_raw.nodes[s]['x'], g_raw.nodes[s]['y']],
[g_raw.nodes[e]['x'], g_raw.nodes[e]['y']]
])
assert line_geom == primal_graph[s][e][k]['geom']
assert line_geom == g_simple[s][e][k]['geom']

# check that missing node keys throw an error
g_copy = g_raw.copy()
for k in ['x', 'y']:
for n in primal_graph.nodes():
for n in g_copy.nodes():
# delete key from first node and break
del primal_graph.nodes[n][k]
del g_copy.nodes[n][k]
break
# check that missing key throws an error
with pytest.raises(KeyError):
graphs.nX_simple_geoms(primal_graph)
graphs.nX_simple_geoms(g_copy)

# check that zero length self-loops are caught and removed
g_copy = g_raw.copy()
g_copy.add_edge(0, 0) # simple geom from self edge = length of zero
g_simple = graphs.nX_simple_geoms(g_copy)
assert not g_simple.has_edge(0, 0)


def test_add_node(diamond_graph):
Expand Down

0 comments on commit 33b75f8

Please sign in to comment.