From b44a72588fd55fd4965525a181412ee7003bfdc3 Mon Sep 17 00:00:00 2001 From: Al Date: Sun, 18 Oct 2015 18:23:27 -0400 Subject: [PATCH] [polygons/osm] Connecting OSM polygons from their constituent ways is an instance of finding strongly connected components in a graph, adding implementation --- scripts/geodata/graph/__init__.py | 0 scripts/geodata/graph/scc.py | 34 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 scripts/geodata/graph/__init__.py create mode 100644 scripts/geodata/graph/scc.py diff --git a/scripts/geodata/graph/__init__.py b/scripts/geodata/graph/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/scripts/geodata/graph/scc.py b/scripts/geodata/graph/scc.py new file mode 100644 index 00000000..e1db8707 --- /dev/null +++ b/scripts/geodata/graph/scc.py @@ -0,0 +1,34 @@ +VISIT, VISIT_EDGE, POST_VISIT = range(3) + + +def strongly_connected_components(graph): + identified = set() + stack = [] + index = {} + boundaries = [] + + for v in graph: + if v not in index: + todo = [(VISIT, v)] + while todo: + op, v = todo.pop() + if op == VISIT: + index[v] = len(stack) + stack.append(v) + boundaries.append(index[v]) + todo.append((POST_VISIT, v)) + todo.extend([(VISIT_EDGE, w) for w in graph[v]]) + elif op == VISIT_EDGE: + if v not in index: + todo.append((VISIT, v)) + elif v not in identified: + while index[v] < boundaries[-1]: + boundaries.pop() + else: + # op == POST_VISIT + if boundaries[-1] == index[v]: + boundaries.pop() + scc = stack[index[v]:] + del stack[index[v]:] + identified.update(scc) + yield scc