diff --git a/mapbuilder/Dockerfile b/mapbuilder/Dockerfile index c425e1f22ca8352c7ead3f63d59bb9c18d6e50fb..94f3f2060b4c80ba07fde68e5450a718bbcf749e 100644 --- a/mapbuilder/Dockerfile +++ b/mapbuilder/Dockerfile @@ -1,6 +1,5 @@ FROM eclipse-temurin:19-jdk-alpine ADD target/*-jar-with-dependencies.jar app.jar -COPY src/main/resources/config.properties /data/configuration/config.properties # Add the cron job # Calculate the map each day at 00:00 diff --git a/mapbuilder/pom.xml b/mapbuilder/pom.xml index c89e4ee59ac0836a19cb73e8a7230e1434f0142f..95de4bd94afd622c6210c2f56956677989c7190c 100644 --- a/mapbuilder/pom.xml +++ b/mapbuilder/pom.xml @@ -86,10 +86,10 @@ <dependencyManagement> - + <dependencies> - + <dependency> <groupId>com.google.protobuf</groupId> diff --git a/mapbuilder/src/main/java/map/builder/App.java b/mapbuilder/src/main/java/map/builder/App.java index cb773aa8823867387a29871121bb12e9b3ccbc84..4e2011a345981ea5ce59a64a1c29215b882d8969 100644 --- a/mapbuilder/src/main/java/map/builder/App.java +++ b/mapbuilder/src/main/java/map/builder/App.java @@ -16,6 +16,11 @@ 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.*; + public class App { public static void main(String[] args) throws IOException { System.out.println("Map builder started!"); @@ -24,29 +29,7 @@ public class App { RoadNetwork.Builder roadNetworkBuilder = RoadNetwork.newBuilder(); 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; - */ - - // 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); + BoundingBox bbox = new BoundingBox(BOUNDING_BOX_MIN_LAT, BOUNDING_BOX_MIN_LON, BOUNDING_BOX_MAX_LAT, BOUNDING_BOX_MAX_LON); List<OSMJsonDto> restrictions = OSMFetcher.fetchTurnRestrictions(bbox); List<OSMJsonDto> roads = OSMFetcher.fetchNodesAndWays(bbox); diff --git a/mapbuilder/src/main/java/map/builder/osm/OSMParser.java b/mapbuilder/src/main/java/map/builder/osm/OSMParser.java index b8bc958a985d8bc8e1277d8c0b9c84efaf76a7e6..98f0a71106dba8f48043d88b111f0ff43ca358b7 100644 --- a/mapbuilder/src/main/java/map/builder/osm/OSMParser.java +++ b/mapbuilder/src/main/java/map/builder/osm/OSMParser.java @@ -41,7 +41,7 @@ public class OSMParser { if (OSMJsonUtils.isWay(dto)) { OSMJsonWayDto wayDto = (OSMJsonWayDto) dto; if (SegmentUtils.isSegmentDrivable(wayDto)) { - SegmentUtils.markEndNodes(wayDto); + SegmentUtils.noteNodeOccurrences(wayDto); } } } @@ -72,6 +72,11 @@ public class OSMParser { } } + /** + * Creates a segment based on the OSM data, however, it ignores the original geometry, if the segment has been split + * @param dto + * @param geometry + */ private void createSegment(OSMJsonWayDto dto, ArrayList<Long> geometry) { long osmId = dto.getOsmId(); ArrayList<Coordinates> line = null; diff --git a/mapbuilder/src/main/java/map/builder/osm/SegmentUtils.java b/mapbuilder/src/main/java/map/builder/osm/SegmentUtils.java index 98ad594dd91291e0dc93e962f1faf1943aacdf99..8999772d7681213e8dd785ba2973d0781888bcf1 100644 --- a/mapbuilder/src/main/java/map/builder/osm/SegmentUtils.java +++ b/mapbuilder/src/main/java/map/builder/osm/SegmentUtils.java @@ -12,7 +12,8 @@ import static de.fuberlin.navigator.protos.map_builder.RoadCategory.*; public class SegmentUtils { // this is a hash-map to allow us to check if a node is a start/end node in linear time private SegmentUtils() {} - private static final HashMap<Long, Boolean> endNodes = new HashMap<>(); + // associated each node ID to the segment IDs of the segments that have this node in their geometry + private static final HashMap<Long, Integer> nodeOccurrenceCount = new HashMap<>(); private static final List<String> drivableRoads = Arrays.asList( "motorway", "trunk", @@ -85,45 +86,48 @@ public class SegmentUtils { return SegmentUtils.speedMap.get(roadCategory); } - public static void markEndNodes(OSMJsonWayDto element) { + public static void noteNodeOccurrences(OSMJsonWayDto element) { long[] nodes = element.getNodes(); + long segmentId = element.getOsmId(); - long startNodeId = nodes[0]; - long endNodeId = nodes[nodes.length - 1]; + for (long nodeId : nodes) { + addNodeToNodeMap(nodeId, segmentId); + } + } - System.out.println("marking " + startNodeId + " and " + endNodeId); + private static void addNodeToNodeMap(long nodeId, long segmentId) { + if (!nodeOccurrenceCount.containsKey(nodeId)) { + nodeOccurrenceCount.put(nodeId, 0); + } - SegmentUtils.endNodes.put(startNodeId, true); - SegmentUtils.endNodes.put(endNodeId, true); + int nodeIdOccurrences = nodeOccurrenceCount.get(nodeId); + nodeOccurrenceCount.put(nodeId, nodeIdOccurrences + 1); } - public static boolean isNodeAnEndNode(long osmId) { - return SegmentUtils.endNodes.containsKey(osmId); + public static boolean isNodeContainedInMultipleSegments(long osmId) { + return nodeOccurrenceCount.containsKey(osmId) && nodeOccurrenceCount.get(osmId) > 1; } public static ArrayList<ArrayList<Long>> splitGeometry(long[] nodes) { ArrayList<ArrayList<Long>> geometry = new ArrayList<>(); - int from = -1; + int from = 0; for (int i = 0; i < nodes.length; i++) { long nodeId = nodes[i]; - if (isNodeAnEndNode(nodeId)) { - if (from == -1) { - from = i; - } - else { - // extract node ids - ArrayList<Long> geometryNodeIds = extractIdsFromTo(nodes, from, i); - geometry.add(geometryNodeIds); - - if (from != 0) { - System.out.println("Splitting at position " + from + ", nodes:"); - } + // extract node IDs only if the node occurs multiple times and is NOT an end-node + if ((isNodeContainedInMultipleSegments(nodeId) && i != 0) + || i == (nodes.length - 1)) { + // extract node ids + ArrayList<Long> geometryNodeIds = extractIdsFromTo(nodes, from, i); + geometry.add(geometryNodeIds); - from = i; + if (from != 0) { + System.out.println("Splitting at position " + from + ", nodes:"); } + + from = i; } } diff --git a/mapbuilder/src/main/java/map/builder/utilities/Config.java b/mapbuilder/src/main/java/map/builder/utilities/Config.java index a8bfe433f1c99260abbdfff19a81d4b72f0d353b..6174447353d6d1c10a05deede0d225e7d2ddf26c 100644 --- a/mapbuilder/src/main/java/map/builder/utilities/Config.java +++ b/mapbuilder/src/main/java/map/builder/utilities/Config.java @@ -14,6 +14,14 @@ public class Config { public static String ROAD_NETWORK_OUTPUT_PATH = "roadnetwork.proto"; + /** + * Bounding box, default small box inside Cottbus + */ + public static float BOUNDING_BOX_MIN_LAT = 51.754092326645475f; + public static float BOUNDING_BOX_MIN_LON = 14.300615062713623f; + public static float BOUNDING_BOX_MAX_LAT = 51.766591637718435f; + public static float BOUNDING_BOX_MAX_LON = 14.314413070678711f; + public static void load() { //The config is used for running the application in a Docker container String configFilePath = "/data/configuration/config.properties"; @@ -21,7 +29,12 @@ public class Config { try (FileInputStream is = new FileInputStream(configFilePath)){ props.load(is); - ROAD_NETWORK_OUTPUT_PATH = props.getProperty("ROAD_NETWORK_OUTPUT_PATH", ROAD_NETWORK_OUTPUT_PATH); + ROAD_NETWORK_OUTPUT_PATH = props.getProperty("MAP_BUILDER_ROAD_NETWORK_OUTPUT_PATH", ROAD_NETWORK_OUTPUT_PATH); + + BOUNDING_BOX_MIN_LAT = Float.parseFloat(props.getProperty("BOUNDING_BOX_MIN_LAT", String.valueOf(BOUNDING_BOX_MIN_LAT))); + BOUNDING_BOX_MIN_LON = Float.parseFloat(props.getProperty("BOUNDING_BOX_MIN_LON", String.valueOf(BOUNDING_BOX_MIN_LON))); + BOUNDING_BOX_MAX_LAT = Float.parseFloat(props.getProperty("BOUNDING_BOX_MAX_LAT", String.valueOf(BOUNDING_BOX_MAX_LAT))); + BOUNDING_BOX_MAX_LON = Float.parseFloat(props.getProperty("BOUNDING_BOX_MAX_LON", String.valueOf(BOUNDING_BOX_MAX_LON))); System.out.println("Config loaded."); } catch (FileNotFoundException e) { // Either way the Docker image was build wrong or this is not diff --git a/mapbuilder/src/main/resources/config.properties b/mapbuilder/src/main/resources/config.properties deleted file mode 100644 index 639d82dd25eeb130babc43a9f4e0bc455c39cdcd..0000000000000000000000000000000000000000 --- a/mapbuilder/src/main/resources/config.properties +++ /dev/null @@ -1,2 +0,0 @@ -# Standard config for Docker -ROAD_NETWORK_OUTPUT_PATH = /data/road_network/roadnetwork.proto \ No newline at end of file