Skip to content
Snippets Groups Projects
Commit 8a4b6435 authored by kraleva's avatar kraleva
Browse files

Merge branch 'add_LLC' into 'main'

Add LLC

See merge request !26
parents 8fcf44c5 a20bc461
Branches
No related tags found
1 merge request!26Add LLC
......@@ -18,6 +18,13 @@
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
......@@ -34,16 +41,12 @@
<artifactId>json</artifactId>
<version>20230227</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>de.fuberlin.navigator</groupId>
<artifactId>proto</artifactId>
<version>1.00.05</version>
<version>1.00.08</version>
</dependency>
</dependencies>
......@@ -79,4 +82,31 @@
<url>https://git.imp.fu-berlin.de/api/v4/projects/8345/packages/maven</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.22.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
package map.builder;
import static map.builder.utilities.Config.ROAD_NETWORK_OUTPUT_PATH;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.osm.json.model.OSMJsonDto;
import map.builder.utilities.BoundingBox;
import map.builder.utilities.Config;
import map.builder.utilities.ConnectedComponentGraph;
import map.builder.utilities.FileHandler;
import java.io.IOException;
import java.util.List;
import static map.builder.utilities.Config.ROAD_NETWORK_OUTPUT_PATH;
public class App {
public static void main(String[] args) throws IOException {
System.out.println("Map builder started!");
Config.load();
RoadNetwork.Builder roadNetworkBuilder = RoadNetwork.newBuilder();
OSMParser parser = new OSMParser(roadNetworkBuilder);
OSMParser parser = new OSMParser();
// A small BBox inside Cottbus
/*
float minLat = 51.765120241998865f;
float minLon = 14.32669617537409f;
float maxLat = 51.77116774623326f;
float maxLon = 14.330334220133722f;
* float minLat = 51.765120241998865f;
* float minLon = 14.32669617537409f;
* float maxLat = 51.77116774623326f;
* float maxLon = 14.330334220133722f;
*/
// BBox around Central + South Brandenburg (about 1.2GB in size)
float minLat = 52.788831211664586f;
float minLon = 11.333053381241731f;
float maxLat = 50.92993593954551f;
float maxLon = 14.714574575766516f;
// smaller BBox inside Cottbus, better for the debug tool
float minLat = 51.754092326645475f;
float minLon = 14.300615062713623f;
float maxLat = 51.766591637718435f;
float maxLon = 14.314413070678711f;
// BBox around Cottbus
/*
* float minLat = 51.714692361306376f;
* float minLon = 14.26197052001953f;
* float maxLat = 51.79290380494767f;
* float maxLon = 14.415779113769531f;
*/
BoundingBox bbox = new BoundingBox(minLat, minLon, maxLat, maxLon);
List<OSMJsonDto> restrictions = OSMFetcher.fetchTurnRestrictions(bbox);
List<OSMJsonDto> roads = OSMFetcher.fetchNodesAndWays(bbox);
System.out.println("Starting to parse.");
parser.parseTurnRestrictions(restrictions);
parser.parseRoads(roads);
System.out.println("Parsed road network.");
RoadNetwork roadNetwork = roadNetworkBuilder.build();
// set it to 0 so that it can be collected by garbage collector
restrictions = null;
roads = null;
bbox = null;
// create the nodes graph in order to run LCC on it
ConnectedComponentGraph graph = new ConnectedComponentGraph();
OSMConnectedComponentParser.addNodes(parser.nodes, graph);
OSMConnectedComponentParser.addEdges(parser.segments, graph);
ArrayList<Long> component = graph.getSCCs();
// cleanup
graph = null;
OSMConnectedComponentParser.cleanUp(parser.nodes, parser.segments, component);
RoadNetwork roadNetwork = roadNetworkBuilder.putAllNodes(parser.nodes).putAllSegments(parser.segments)
.addAllTurnRestrictions(parser.restrictions).build();
System.out.println("Turn restrictions count: " + roadNetwork.getTurnRestrictionsCount());
System.out.println("Nodes count: " + roadNetwork.getNodesCount());
System.out.println("Segments count: " + roadNetwork.getSegmentsCount());
......
package map.builder.osm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import de.fuberlin.navigator.protos.map_builder.Node;
import de.fuberlin.navigator.protos.map_builder.Segment;
import map.builder.utilities.ConnectedComponentGraph;
public class OSMConnectedComponentParser {
public static void addNodes(Map<Long, Node> nodesMap, ConnectedComponentGraph graph) {
for (Long nodeId : nodesMap.keySet()) {
graph.addNode(nodeId);
}
}
public static void addEdges(Map<Long, Segment> segmentsMap, ConnectedComponentGraph graph) {
for (Long edgeId : segmentsMap.keySet()) {
Segment segment = segmentsMap.get(edgeId);
Long startNode = segment.getStartNode();
Long endNode = segment.getEndNode();
graph.addEdge(startNode, endNode);
if (!segment.getOneWay()) {
graph.addEdge(endNode, startNode);
}
}
}
public static void cleanUp(Map<Long, Node> nodesMap, Map<Long, Segment> segmentsMap, ArrayList<Long> component) {
nodesMap.keySet().retainAll(Collections.unmodifiableCollection(component));
ArrayList<Long> segmentIDsToRemove = new ArrayList<Long>();
for (Long key : segmentsMap.keySet()) {
Segment segment = segmentsMap.get(key);
Long startNodeID = segment.getStartNode();
Long endNodeID = segment.getEndNode();
if ((!component.contains(startNodeID)) && (!component.contains(endNodeID))) {
segmentIDsToRemove.add(key);
}
}
segmentsMap.keySet().removeAll(segmentIDsToRemove);
}
}
\ No newline at end of file
package map.builder.osm;
import java.io.BufferedReader;
import static map.builder.osm.json.serialization.OSMJsonDtoDeserializer.Mode.NODES_AND_WAYS;
import static map.builder.osm.json.serialization.OSMJsonDtoDeserializer.Mode.TURN_RESTRICTIONS;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileWriter;
......@@ -16,15 +18,11 @@ import java.util.stream.Collectors;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import map.builder.osm.json.model.OSMJsonDto;
import map.builder.osm.json.serialization.OSMJsonDtoDeserializer;
import org.json.JSONObject;
import map.builder.utilities.BoundingBox;
import static map.builder.osm.json.serialization.OSMJsonDtoDeserializer.Mode.NODES_AND_WAYS;
import static map.builder.osm.json.serialization.OSMJsonDtoDeserializer.Mode.TURN_RESTRICTIONS;
public class OSMFetcher {
private final static String OverpassURL = "https://overpass.kumi.systems/api/interpreter";
private final static String nodeQuery = "[out:json];way[highway](%s);(._;>;);out;";
......@@ -49,7 +47,8 @@ public class OSMFetcher {
return dtos;
}
private static List<OSMJsonDto> runQueryForBBox(String query, BoundingBox bbox, OSMJsonDtoDeserializer.Mode mode) throws IOException {
private static List<OSMJsonDto> runQueryForBBox(String query, BoundingBox bbox, OSMJsonDtoDeserializer.Mode mode)
throws IOException {
InputStream response = requestData(query, bbox);
JsonReader jsonReader = new JsonReader(new InputStreamReader(response));
......@@ -107,8 +106,7 @@ public class OSMFetcher {
data.stream()
.map(OSMJsonDto::toJson)
.collect(Collectors.joining(", "))
+ "]"
);
+ "]");
file.close();
}
}
......@@ -4,24 +4,28 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import map.builder.osm.json.model.*;
import de.fuberlin.navigator.protos.map_builder.Coordinates;
import de.fuberlin.navigator.protos.map_builder.Node;
import de.fuberlin.navigator.protos.map_builder.Restriction;
import de.fuberlin.navigator.protos.map_builder.RoadNetwork;
import de.fuberlin.navigator.protos.map_builder.Segment;
import map.builder.osm.json.model.OSMJsonDto;
import map.builder.osm.json.model.OSMJsonMemberDto;
import map.builder.osm.json.model.OSMJsonNodeDto;
import map.builder.osm.json.model.OSMJsonTurnRestrictionDto;
import map.builder.osm.json.model.OSMJsonWayDto;
import map.builder.utilities.ComputationalUtils;
public class OSMParser {
private final Coordinates.Builder coordinatesBuilder;
private final HashMap<Long, Node> nodesDump;
RoadNetwork.Builder roadNetworkBuilder;
public OSMParser(RoadNetwork.Builder roadNetworkBuilder) {
this.roadNetworkBuilder = roadNetworkBuilder;
// maps to put the entries
public HashMap<Long, Node> nodes = new HashMap<Long, Node>();
public HashMap<Long, Segment> segments = new HashMap<Long, Segment>();
public ArrayList<Restriction> restrictions = new ArrayList<Restriction>();
public OSMParser() {
this.coordinatesBuilder = Coordinates.newBuilder();
this.nodesDump = new HashMap<>();
}
......@@ -50,6 +54,7 @@ public class OSMParser {
}
}
}
}
private void splitSegment(OSMJsonWayDto dto) {
......@@ -73,8 +78,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 +90,12 @@ public class OSMParser {
boolean oneWay = SegmentUtils.isSegmentOneway(dto);
int maxSpeed = SegmentUtils.getMaxSpeed(dto);
int internalId = this.roadNetworkBuilder.getSegmentsCount();
System.out.printf("Max speed: %d \n", maxSpeed);
System.out.printf("Way id: %d, Start node id : %d, End node id: %d \n", osmId,
this.nodes.get(startNodeId).getId(),
this.nodes.get(endNodeId).getId());
long internalId = this.segments.size();
Segment segment = Segment.newBuilder()
.setOsmId(osmId)
......@@ -100,19 +109,19 @@ public class OSMParser {
.setLength(this.computeSegmentLength(line))
.build();
this.roadNetworkBuilder.putSegments(internalId, segment);
this.segments.put(internalId, segment);
}
private void moveNodeToProto(Node node) {
long osmId = node.getOsmId();
this.roadNetworkBuilder.putNodes(osmId, node);
this.nodes.put(osmId, node);
}
private void createNode(OSMJsonNodeDto dto) {
Coordinates position = this.createLocationFromElement(dto.getLon(), dto.getLat());
Node node = Node.newBuilder()
.setId(this.roadNetworkBuilder.getNodesCount())
.setId(this.nodes.size() + this.nodesDump.size())
.setOsmId(dto.getOsmId())
.setPosition(position)
.build();
......@@ -134,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
......@@ -168,12 +179,11 @@ public class OSMParser {
private Node findParsedNodeById(long osmId) throws NullPointerException {
if (this.nodesDump.containsKey(osmId)) {
Node node = this.nodesDump.get(osmId);
return node;
}
if (this.roadNetworkBuilder.getNodesMap().containsKey(osmId)) {
return this.roadNetworkBuilder.getNodesMap().get(osmId);
if (this.nodes.containsKey(osmId)) {
return this.nodes.get(osmId);
}
throw new NullPointerException("Node with id " + osmId + " not found!");
......@@ -210,7 +220,7 @@ public class OSMParser {
}
}
Restriction restriction = Restriction.newBuilder().setFromId(from).setToId(to).build();
this.roadNetworkBuilder.addTurnRestrictions(restriction);
this.restrictions.add(restriction);
}
}
......
......@@ -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) {
......
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
public class ConnectedComponentGraph {
private HashMap<Long, LinkedList<Long>> adj; // Adjacency List
// Constructor
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(Long v, Long w) {
adj.get(v).add(w);
}
// A recursive function to print DFS starting from v
public ArrayList<Long> DFSUtil(Long v, HashMap<Long, Boolean> visited) {
// Mark the current node as visited and print it
visited.put(v, true);
ArrayList<Long> component = new ArrayList<Long>();
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))
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();
for (Long v : adj.keySet()) {
g.addNode(v);
}
for (Long v : adj.keySet()) {
// Recur for all the vertices adjacent to this vertex
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(Long v, HashMap<Long, Boolean> visited, Stack<Long> stack) {
// Mark the current node as visited and print it
visited.put(v, true);
// Recur for all the vertices adjacent to this vertex
Iterator<Long> i = adj.get(v).iterator();
while (i.hasNext()) {
Long n = i.next();
if (!visited.get(n))
fillOrder(n, visited, stack);
}
// All vertices reachable from v are processed by now,
// push v to Stack
stack.push(v);
}
// The main function that finds and prints all strongly
// connected components
public ArrayList<Long> getSCCs() {
Stack<Long> stack = new Stack<Long>();
// Mark all the vertices as not visited (For first DFS)
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 (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 (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
Long v = stack.pop();
// Print Strongly connected component of the popped vertex
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();
// 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.getSCCs();
}
}
// This code is contributed by Aakash Hasija
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment