diff --git a/mapbuilder/pom.xml b/mapbuilder/pom.xml index 18f285b041c5b2a2109678745c027f1b4721fbab..5f81a98ff8d1755e5614d603be46d8889f0484d7 100644 --- a/mapbuilder/pom.xml +++ b/mapbuilder/pom.xml @@ -42,7 +42,7 @@ <dependency> <groupId>de.fuberlin.navigator</groupId> <artifactId>proto</artifactId> - <version>1.00.06</version> + <version>1.00.08</version> </dependency> </dependencies> diff --git a/mapbuilder/src/main/java/map/builder/App.java b/mapbuilder/src/main/java/map/builder/App.java index 9a8b352f486f86dc0f9b424448c16f391cbdb513..86d03c863ede7e1d5df4ffdeab761cd179bb9ddb 100644 --- a/mapbuilder/src/main/java/map/builder/App.java +++ b/mapbuilder/src/main/java/map/builder/App.java @@ -1,13 +1,16 @@ package map.builder; import java.io.IOException; +import java.util.ArrayList; import org.json.JSONArray; import de.fuberlin.navigator.protos.map_builder.RoadNetwork; +import map.builder.osm.OSMConnectedComponentParser; import map.builder.osm.OSMFetcher; import map.builder.osm.OSMParser; import map.builder.utilities.BoundingBox; +import map.builder.utilities.ConnectedComponentGraph; import map.builder.utilities.FileHandler; public class App { @@ -46,6 +49,23 @@ public class App { parser.parseTurnRestrictions(restrictions); parser.parseRoads(roads); + // set it to 0 so that it can be collected by garbage collector + restrictions = null; + roads = null; + bbox = null; + parser = null; + + // create the nodes graph in order to run LCC on it + ConnectedComponentGraph graph = new ConnectedComponentGraph(); + OSMConnectedComponentParser.addNodes(roadNetworkBuilder, graph); + OSMConnectedComponentParser.addEdges(roadNetworkBuilder, graph); + + ArrayList<Long> component = graph.getSCCs(); + System.out.println(component.toString()); + + // cleanup + graph = null; + RoadNetwork roadNetwork = roadNetworkBuilder.build(); System.out.println("Turn restrictions count: " + roadNetwork.getTurnRestrictionsCount()); System.out.println("Nodes count: " + roadNetwork.getNodesCount()); diff --git a/mapbuilder/src/main/java/map/builder/osm/OSMConnectedComponentParser.java b/mapbuilder/src/main/java/map/builder/osm/OSMConnectedComponentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..003ba3ca6055ccf7332646b1806bf9026c0341a8 --- /dev/null +++ b/mapbuilder/src/main/java/map/builder/osm/OSMConnectedComponentParser.java @@ -0,0 +1,27 @@ +package map.builder.osm; + +import de.fuberlin.navigator.protos.map_builder.RoadNetwork; +import de.fuberlin.navigator.protos.map_builder.Segment; +import map.builder.utilities.ConnectedComponentGraph; + +public class OSMConnectedComponentParser { + + public static void addNodes(RoadNetwork.Builder roadnetwowrBuilder, ConnectedComponentGraph graph) { + for (Long nodeId : roadnetwowrBuilder.getNodesMap().keySet()) { + graph.addNode(nodeId); + } + } + + public static void addEdges(RoadNetwork.Builder roadnetworkbuilder, ConnectedComponentGraph graph) { + for (Long edgeId : roadnetworkbuilder.getSegmentsMap().keySet()) { + Segment segment = roadnetworkbuilder.getSegmentsMap().get(edgeId); + Long startNode = segment.getStartNode(); + Long endNode = segment.getEndNode(); + graph.addEdge(startNode, endNode); + if (!segment.getOneWay()) { + graph.addEdge(endNode, startNode); + } + } + } + +} \ No newline at end of file diff --git a/mapbuilder/src/main/java/map/builder/osm/OSMParser.java b/mapbuilder/src/main/java/map/builder/osm/OSMParser.java index bf8b7822a2a5a100c79871e60e809c295f7e5d86..b30da2f941172a5b884657a754c2353f8bc625c8 100644 --- a/mapbuilder/src/main/java/map/builder/osm/OSMParser.java +++ b/mapbuilder/src/main/java/map/builder/osm/OSMParser.java @@ -2,8 +2,6 @@ package map.builder.osm; import java.util.ArrayList; import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.json.JSONArray; import org.json.JSONObject; @@ -18,7 +16,7 @@ import map.builder.utilities.ComputationalUtils; public class OSMParser { private final Coordinates.Builder coordinatesBuilder; private final HashMap<Long, Node> nodesDump; - RoadNetwork.Builder roadNetworkBuilder; + public RoadNetwork.Builder roadNetworkBuilder; public OSMParser(RoadNetwork.Builder roadNetworkBuilder) { this.roadNetworkBuilder = roadNetworkBuilder; @@ -49,6 +47,7 @@ public class OSMParser { this.splitSegment(element); } } + } private void splitSegment(JSONObject element) { @@ -61,7 +60,7 @@ public class OSMParser { System.out.println("Split segment with ID " + osmId + " in " + geometry.size()); } - for (int i = 0; i<geometry.size(); i++) { + for (int i = 0; i < geometry.size(); i++) { this.createSegment(element, geometry.get(i)); } } @@ -72,8 +71,7 @@ public class OSMParser { try { line = this.findNodePositions(geometry); - } - catch (NullPointerException e) { + } catch (NullPointerException e) { System.out.println("Dropping segment with ID " + osmId); System.out.println(e.getMessage()); return; @@ -86,7 +84,9 @@ public class OSMParser { int maxSpeed = SegmentUtils.getMaxSpeed(element); System.out.printf("Max speed: %d \n", maxSpeed); - System.out.printf("Way id: %d, Start node id : %d, End node id: %d \n", osmId, startNodeId, endNodeId); + System.out.printf("Way id: %d, Start node id : %d, End node id: %d \n", osmId, + this.roadNetworkBuilder.getNodesMap().get(startNodeId).getId(), + this.roadNetworkBuilder.getNodesMap().get(endNodeId).getId()); long internalId = this.roadNetworkBuilder.getSegmentsCount(); @@ -107,13 +107,13 @@ public class OSMParser { private boolean isOneWay(JSONObject element) { return OSMJSONUtils.isTagValueEqualTo(element, "oneway", "yes") || - OSMJSONUtils.isTagValueEqualTo(element, "highway", "motorway") || - OSMJSONUtils.isTagValueEqualTo(element, "junction", "roundabout"); + OSMJSONUtils.isTagValueEqualTo(element, "highway", "motorway") || + OSMJSONUtils.isTagValueEqualTo(element, "junction", "roundabout"); } private void moveNodeToProto(Node node) { long osmId = node.getOsmId(); - this.roadNetworkBuilder.putNodes(osmId, node); + this.roadNetworkBuilder.putNodes(node.getOsmId(), node); } private void createNode(JSONObject element) { @@ -121,7 +121,7 @@ public class OSMParser { long osmId = element.getLong(OSMKey.id.name()); Node node = Node.newBuilder() - .setId(this.roadNetworkBuilder.getNodesCount()) + .setId(this.roadNetworkBuilder.getNodesCount() + this.nodesDump.size()) .setOsmId(osmId) .setPosition(position) .build(); @@ -143,8 +143,10 @@ public class OSMParser { } /** - * Returns an array list of array lists of geometries. If the outer list has only one entry, it means the segment + * Returns an array list of array lists of geometries. If the outer list has + * only one entry, it means the segment * doesn't need to be split, otherwise it needs to. + * * @param nodeIds * @return * @throws NullPointerException @@ -176,7 +178,6 @@ public class OSMParser { private Node findParsedNodeById(long osmId) throws NullPointerException { if (this.nodesDump.containsKey(osmId)) { Node node = this.nodesDump.get(osmId); - return node; } diff --git a/mapbuilder/src/main/java/map/builder/utilities/ComputationalUtils.java b/mapbuilder/src/main/java/map/builder/utilities/ComputationalUtils.java index 706865e78abdb592c2f15cfef075ca60857f069a..371b6e3358ee70d1b79fb7377b46d1bcb9911aed 100644 --- a/mapbuilder/src/main/java/map/builder/utilities/ComputationalUtils.java +++ b/mapbuilder/src/main/java/map/builder/utilities/ComputationalUtils.java @@ -3,8 +3,6 @@ package map.builder.utilities; import de.fuberlin.navigator.protos.map_builder.Coordinates; public class ComputationalUtils { - private ComputationalUtils() { - } public static double haversine(Coordinates position_0, de.fuberlin.navigator.protos.map_builder.Coordinates position_1) { diff --git a/mapbuilder/src/main/java/map/builder/utilities/ConnectedComponentGraph.java b/mapbuilder/src/main/java/map/builder/utilities/ConnectedComponentGraph.java index 18102d43b3b1ac538f2e3df8ae9db587854bcc42..9504289a703259db68c28ad8783f63c2ca125eac 100644 --- a/mapbuilder/src/main/java/map/builder/utilities/ConnectedComponentGraph.java +++ b/mapbuilder/src/main/java/map/builder/utilities/ConnectedComponentGraph.java @@ -1,68 +1,94 @@ package map.builder.utilities; +import java.util.ArrayList; +import java.util.HashMap; // Code from : https://www.geeksforgeeks.org/strongly-connected-components/ // Java implementation of Kosaraju's algorithm to print all SCCs import java.util.Iterator; import java.util.LinkedList; import java.util.Stack; +//TODO: change data structure here to be more appropriate // This class represents a directed ConnectedComponentGraph using adjacency list // representation -class ConnectedComponentGraph { - private int V; // No. of vertices - private LinkedList<Integer> adj[]; // Adjacency List +public class ConnectedComponentGraph { + private HashMap<Long, LinkedList<Long>> adj; // Adjacency List // Constructor - ConnectedComponentGraph(int v) { - V = v; - adj = new LinkedList[v]; - for (int i = 0; i < v; ++i) - adj[i] = new LinkedList<Integer>(); + public ConnectedComponentGraph() { + adj = new HashMap<Long, LinkedList<Long>>(); + } + + public void addNode(Long v) { + adj.put(v, new LinkedList<Long>()); } // Function to add an edge into the ConnectedComponentGraph - public void addEdge(int v, int w) { - adj[v].add(w); + public void addEdge(Long v, Long w) { + adj.get(v).add(w); } // A recursive function to print DFS starting from v - public void DFSUtil(int v, boolean visited[]) { + public ArrayList<Long> DFSUtil(Long v, HashMap<Long, Boolean> visited) { // Mark the current node as visited and print it - visited[v] = true; - System.out.print(v + " "); + visited.put(v, true); - int n; + ArrayList<Long> component = new ArrayList<Long>(); + Long n; // Recur for all the vertices adjacent to this vertex - Iterator<Integer> i = adj[v].iterator(); + Iterator<Long> i = adj.get(v).iterator(); while (i.hasNext()) { n = i.next(); - if (!visited[n]) - DFSUtil(n, visited); + if (!visited.get(n)) + component = DFSUtil(n, visited, component); } + component.add(v); + return component; + } + + public ArrayList<Long> DFSUtil(Long v, HashMap<Long, Boolean> visited, ArrayList<Long> list) { + // Mark the current node as visited and print it + visited.put(v, true); + Long n; + + // Recur for all the vertices adjacent to this vertex + Iterator<Long> i = adj.get(v).iterator(); + while (i.hasNext()) { + n = i.next(); + if (!visited.get(n)) + DFSUtil(n, visited, list); + } + list.add(v); + return list; } // Function that returns reverse (or transpose) of this ConnectedComponentGraph public ConnectedComponentGraph getTranspose() { - ConnectedComponentGraph g = new ConnectedComponentGraph(V); - for (int v = 0; v < V; v++) { + ConnectedComponentGraph g = new ConnectedComponentGraph(); + for (Long v : adj.keySet()) { + g.addNode(v); + } + for (Long v : adj.keySet()) { // Recur for all the vertices adjacent to this vertex - Iterator<Integer> i = adj[v].listIterator(); - while (i.hasNext()) - g.adj[i.next()].add(v); + Iterator<Long> i = adj.get(v).listIterator(); + while (i.hasNext()) { + Long next = i.next(); + g.adj.get(next).add(v); + } } return g; } - public void fillOrder(int v, boolean visited[], Stack<Integer> stack) { + public void fillOrder(Long v, HashMap<Long, Boolean> visited, Stack<Long> stack) { // Mark the current node as visited and print it - visited[v] = true; + visited.put(v, true); // Recur for all the vertices adjacent to this vertex - Iterator<Integer> i = adj[v].iterator(); + Iterator<Long> i = adj.get(v).iterator(); while (i.hasNext()) { - int n = i.next(); - if (!visited[n]) + Long n = i.next(); + if (!visited.get(n)) fillOrder(n, visited, stack); } @@ -73,53 +99,67 @@ class ConnectedComponentGraph { // The main function that finds and prints all strongly // connected components - public void printSCCs() { - Stack<Integer> stack = new Stack<Integer>(); + public ArrayList<Long> getSCCs() { + Stack<Long> stack = new Stack<Long>(); // Mark all the vertices as not visited (For first DFS) - boolean visited[] = new boolean[V]; - for (int i = 0; i < V; i++) - visited[i] = false; + HashMap<Long, Boolean> visited = new HashMap<Long, Boolean>(); + for (Long i : this.adj.keySet()) { + visited.put(i, false); + } // Fill vertices in stack according to their finishing // times - for (int i = 0; i < V; i++) - if (visited[i] == false) + for (Long i : this.adj.keySet()) + if (visited.get(i) == false) fillOrder(i, visited, stack); // Create a reversed ConnectedComponentGraph ConnectedComponentGraph gr = getTranspose(); // Mark all the vertices as not visited (For second DFS) - for (int i = 0; i < V; i++) - visited[i] = false; + for (Long i : this.adj.keySet()) + visited.put(i, false); // Now process all vertices in order defined by Stack + ArrayList<Long> largestComponent = new ArrayList<Long>(); + int maxLength = 0; while (stack.empty() == false) { // Pop a vertex from stack - int v = (int) stack.pop(); + Long v = stack.pop(); // Print Strongly connected component of the popped vertex - if (visited[v] == false) { - gr.DFSUtil(v, visited); - System.out.println(); + if (visited.get(v) == false) { + ArrayList<Long> component = gr.DFSUtil(v, visited); + if (maxLength < component.size()) { + maxLength = component.size(); + largestComponent = component; + } } } + return largestComponent; } // Driver method public static void main(String args[]) { // Create a ConnectedComponentGraph given in the above diagram - ConnectedComponentGraph g = new ConnectedComponentGraph(5); - g.addEdge(1, 0); - g.addEdge(0, 2); - g.addEdge(2, 1); - g.addEdge(0, 3); - g.addEdge(3, 4); + ConnectedComponentGraph g = new ConnectedComponentGraph(); + // add nodes + g.addNode((long) 0); + g.addNode((long) 1); + g.addNode((long) 2); + g.addNode((long) 3); + g.addNode((long) 4); + + g.addEdge((long) 1, (long) 0); + g.addEdge((long) 0, (long) 2); + g.addEdge((long) 2, (long) 1); + g.addEdge((long) 0, (long) 3); + g.addEdge((long) 3, (long) 4); System.out.println("Following are strongly connected components " + "in given ConnectedComponentGraph "); - g.printSCCs(); + g.getSCCs(); } } // This code is contributed by Aakash Hasija \ No newline at end of file