From a8f3559c07aba524562361bbed2d3bf532bd76e4 Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 11 Mar 2024 13:10:17 +0100 Subject: [PATCH] feat: Add experimental cargo bike profile (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * First changes * second part * Third part * Changes for junction * Implement availability of junction tags Junctions are not handled by ORS. They need to be implemented and tested, similar to how Tollways are handled. - Create a new type for junctions (JunctionType.java) - Create an Extractor to fetch junctions (JunctionExtractor.java) - Create a place to store junctions (JunctionGraphStorage.java) - To create a storage implement a StorageBuilder (JunctionGraphStorageBuilder.java) - Add junction tag in other necessary places (APIEnums| AvoidFeaturesEdgeFilter | ...) - Remove Tollways from "ors-engine/src/main/resources/META-INF/services/org.heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder" - Add tests for new files (JunctionGraphStorageBuilderTest.java) * Modify route visualization w/ folium * Copy green_streets_hd.csv file and build graph * Add more routes to apicaller.ipynb * Add cycling infrastructure on small streets * Remove special character * Set-up for aws environment * Update .dockerignore * Update .dockerignore * Update .dockerignore * Update .gitignore * Update ors-config.json * Update .rpm-packaging/ors-config.json * Delete .vscode/settings.json * Update docker-compose.yml * Update docker-compose.yml * Update docker-compose.yml * Update docker-compose.yml * Update .dockerignore * Delete modified.sh * Update ors-config.yml * Update ors-config.yml * Update ors-config.yml * Update ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java * Update ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java * Update ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfile.java * Update ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java * Update ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java * Delete requirements.txt * Apply suggestions from code review * Delete subprocess.sql * Delete testtools/requirements.txt * Delete testtools/apicaller.ipynb * Update ors-config.json * Update ors-config.json * Update ors-config.yml * Update .dockerignore * Apply suggestions from code review * Update APIEnums.java * Update RequestProfileParamsWeightings.java * Update .dockerignore --- .dockerignore | 2 +- .../java/org/heigit/ors/api/APIEnums.java | 4 +- .../api/requests/common/RequestOptions.java | 2 +- .../APIMatrixRequestProfileConverterTest.java | 3 + .../api/requests/routing/APIEnumsTest.java | 5 + .../ors/api/services/RoutingServiceTest.java | 19 +++ .../ors/apitests/routing/ParamsTest.java | 1 + .../services/RoutingServiceGreenTest.java | 50 ++++++++ .../heigit/ors/routing/AvoidFeatureFlags.java | 4 +- .../ors/routing/RoutingProfileType.java | 6 + .../graphhopper/extensions/JunctionType.java | 62 +++++++++ .../ORSDefaultFlagEncoderFactory.java | 8 ++ .../graphhopper/extensions/OSMTags.java | 1 + .../edgefilters/AvoidFeaturesEdgeFilter.java | 8 ++ .../flagencoders/FlagEncoderNames.java | 1 + .../bike/CargoBikeFlagEncoder.java | 118 ++++++++++++++++++ .../storages/JunctionGraphStorage.java | 115 +++++++++++++++++ .../builders/JunctionGraphStorageBuilder.java | 93 ++++++++++++++ .../WayCategoryGraphStorageBuilder.java | 4 + .../pathprocessors/JunctionExtractor.java | 81 ++++++++++++ .../CargoBikeFlagEncoderTest.java | 54 ++++++++ .../JunctionGraphStorageBuilderTest.java | 41 ++++++ 22 files changed, 678 insertions(+), 4 deletions(-) create mode 100644 ors-api/src/test/java/org/heigit/ors/apitests/services/RoutingServiceGreenTest.java create mode 100644 ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/JunctionType.java create mode 100644 ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CargoBikeFlagEncoder.java create mode 100644 ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/JunctionGraphStorage.java create mode 100644 ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilder.java create mode 100644 ors-engine/src/main/java/org/heigit/ors/routing/pathprocessors/JunctionExtractor.java create mode 100644 ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CargoBikeFlagEncoderTest.java create mode 100644 ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilderTest.java diff --git a/.dockerignore b/.dockerignore index 7bc9742d68..4cc2ad445c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -36,4 +36,4 @@ docs/ .github/ Dockerfile envs/ -.jqwik-database \ No newline at end of file +.jqwik-database diff --git a/ors-api/src/main/java/org/heigit/ors/api/APIEnums.java b/ors-api/src/main/java/org/heigit/ors/api/APIEnums.java index 39b46ef9ce..dbe2a6b117 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/APIEnums.java +++ b/ors-api/src/main/java/org/heigit/ors/api/APIEnums.java @@ -240,7 +240,8 @@ public enum AvoidFeatures { TOLLWAYS("tollways"), FERRIES("ferries"), FORDS("fords"), - STEPS("steps"); + STEPS("steps"), + JUNCTION("junction"); private final String value; @@ -299,6 +300,7 @@ public enum Profile { CYCLING_ROAD("cycling-road"), CYCLING_MOUNTAIN("cycling-mountain"), CYCLING_ELECTRIC("cycling-electric"), + CYCLING_CARGO("cycling-cargo"), FOOT_WALKING("foot-walking"), FOOT_HIKING("foot-hiking"), WHEELCHAIR("wheelchair"), diff --git a/ors-api/src/main/java/org/heigit/ors/api/requests/common/RequestOptions.java b/ors-api/src/main/java/org/heigit/ors/api/requests/common/RequestOptions.java index a7f8e57105..40c5b714f2 100644 --- a/ors-api/src/main/java/org/heigit/ors/api/requests/common/RequestOptions.java +++ b/ors-api/src/main/java/org/heigit/ors/api/requests/common/RequestOptions.java @@ -34,7 +34,7 @@ public class RequestOptions implements RouteRequestParameterNames { @Schema(name = PARAM_AVOID_FEATURES, description = "List of features to avoid. ", extensions = {@Extension(name = "itemRestrictions", properties = { @ExtensionProperty(name = "ref", value = "profile"), - @ExtensionProperty(name = "itemsWhen", value = "{\"driving-*\":[\"highways\",\"tollways\",\"ferries\"],\"cycling-*\":[\"ferries\",\"steps\",\"fords\"],\"foot-*\":[\"ferries\",\"fords\",\"steps\"],\"wheelchair\":[\"ferries\",\"steps\"]}", parseValue = true)} + @ExtensionProperty(name = "itemsWhen", value = "{\"driving-*\":[\"highways\",\"tollways\",\"ferries\"],\"cycling-*\":[\"ferries\",\"steps\",\"fords\",\"junction\"],\"foot-*\":[\"ferries\",\"fords\",\"steps\"],\"wheelchair\":[\"ferries\",\"steps\"]}", parseValue = true)} )}, example = "[\"highways\"]") @JsonProperty(PARAM_AVOID_FEATURES) diff --git a/ors-api/src/test/java/org/heigit/ors/api/converters/APIMatrixRequestProfileConverterTest.java b/ors-api/src/test/java/org/heigit/ors/api/converters/APIMatrixRequestProfileConverterTest.java index 15b8c05d1c..724f9e28b1 100644 --- a/ors-api/src/test/java/org/heigit/ors/api/converters/APIMatrixRequestProfileConverterTest.java +++ b/ors-api/src/test/java/org/heigit/ors/api/converters/APIMatrixRequestProfileConverterTest.java @@ -9,6 +9,7 @@ class APIMatrixRequestProfileConverterTest { private APIEnums.Profile cyclingElectric; + private APIEnums.Profile cyclingCargo; private APIEnums.Profile cyclingMountain; private APIEnums.Profile cyclingRegular; private APIEnums.Profile cyclingRoad; @@ -23,6 +24,7 @@ class APIMatrixRequestProfileConverterTest { @BeforeEach void setUp() { cyclingElectric = APIEnums.Profile.CYCLING_ELECTRIC; + cyclingCargo = APIEnums.Profile.CYCLING_CARGO; cyclingMountain = APIEnums.Profile.CYCLING_MOUNTAIN; cyclingRegular = APIEnums.Profile.CYCLING_REGULAR; cyclingRoad = APIEnums.Profile.CYCLING_ROAD; @@ -42,6 +44,7 @@ void convert() { assertEquals(cyclingRoad, apiRequestProfileConverter.convert("cycling-road")); assertEquals(cyclingMountain, apiRequestProfileConverter.convert("cycling-mountain")); assertEquals(cyclingElectric, apiRequestProfileConverter.convert("cycling-electric")); + assertEquals(cyclingCargo, apiRequestProfileConverter.convert("cycling-cargo")); assertEquals(footWalking, apiRequestProfileConverter.convert("foot-walking")); assertEquals(footHiking, apiRequestProfileConverter.convert("foot-hiking")); assertEquals(wheelchair, apiRequestProfileConverter.convert("wheelchair")); diff --git a/ors-api/src/test/java/org/heigit/ors/api/requests/routing/APIEnumsTest.java b/ors-api/src/test/java/org/heigit/ors/api/requests/routing/APIEnumsTest.java index e18b87c0a2..6f5c886831 100644 --- a/ors-api/src/test/java/org/heigit/ors/api/requests/routing/APIEnumsTest.java +++ b/ors-api/src/test/java/org/heigit/ors/api/requests/routing/APIEnumsTest.java @@ -104,6 +104,7 @@ void testAvoidFeaturesEnumCreation() throws ParameterValueException { assertEquals(APIEnums.AvoidFeatures.HIGHWAYS, APIEnums.AvoidFeatures.forValue("highways")); assertEquals(APIEnums.AvoidFeatures.STEPS, APIEnums.AvoidFeatures.forValue("steps")); assertEquals(APIEnums.AvoidFeatures.TOLLWAYS, APIEnums.AvoidFeatures.forValue("tollways")); + assertEquals(APIEnums.AvoidFeatures.JUNCTION, APIEnums.AvoidFeatures.forValue("junction")); assertThrows(ParameterValueException.class, () -> APIEnums.AvoidFeatures.forValue("invalid")); } @@ -114,6 +115,8 @@ void testAvoidFeaturesEnumValue() { assertEquals("highways", APIEnums.AvoidFeatures.HIGHWAYS.toString()); assertEquals("steps", APIEnums.AvoidFeatures.STEPS.toString()); assertEquals("tollways", APIEnums.AvoidFeatures.TOLLWAYS.toString()); + assertEquals("junction", APIEnums.AvoidFeatures.JUNCTION.toString()); + } @Test @@ -139,6 +142,7 @@ void testProfileEnumCreation() throws ParameterValueException { assertEquals(APIEnums.Profile.CYCLING_ROAD, APIEnums.Profile.forValue("cycling-road")); assertEquals(APIEnums.Profile.CYCLING_MOUNTAIN, APIEnums.Profile.forValue("cycling-mountain")); assertEquals(APIEnums.Profile.CYCLING_ELECTRIC, APIEnums.Profile.forValue("cycling-electric")); + assertEquals(APIEnums.Profile.CYCLING_CARGO, APIEnums.Profile.forValue("cycling-cargo")); assertEquals(APIEnums.Profile.FOOT_WALKING, APIEnums.Profile.forValue("foot-walking")); assertEquals(APIEnums.Profile.FOOT_HIKING, APIEnums.Profile.forValue("foot-hiking")); assertEquals(APIEnums.Profile.WHEELCHAIR, APIEnums.Profile.forValue("wheelchair")); @@ -153,6 +157,7 @@ void testProfileEnumValue() { assertEquals("cycling-road", APIEnums.Profile.CYCLING_ROAD.toString()); assertEquals("cycling-mountain", APIEnums.Profile.CYCLING_MOUNTAIN.toString()); assertEquals("cycling-electric", APIEnums.Profile.CYCLING_ELECTRIC.toString()); + assertEquals("cycling-cargo", APIEnums.Profile.CYCLING_CARGO.toString()); assertEquals("foot-walking", APIEnums.Profile.FOOT_WALKING.toString()); assertEquals("foot-hiking", APIEnums.Profile.FOOT_HIKING.toString()); assertEquals("wheelchair", APIEnums.Profile.WHEELCHAIR.toString()); diff --git a/ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java b/ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java index 5d7be54525..4f1173a80c 100644 --- a/ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java +++ b/ors-api/src/test/java/org/heigit/ors/api/services/RoutingServiceTest.java @@ -190,6 +190,7 @@ void convertRouteRequestTest() throws Exception { assertEquals(BordersExtractor.Avoid.CONTROLLED, routingRequest.getSearchParameters().getAvoidBorders()); assertArrayEquals(new int[]{115}, routingRequest.getSearchParameters().getAvoidCountries()); assertEquals(AvoidFeatureFlags.getFromString("fords"), routingRequest.getSearchParameters().getAvoidFeatureTypes()); + assertTrue(AvoidFeatureFlags.isValid(18,32)); checkPolygon(routingRequest.getSearchParameters().getAvoidAreas(), geoJsonPolygon); @@ -243,6 +244,24 @@ void TestWheelchairParameters() throws Exception { assertTrue(params.allowUnsuitable()); } + @Test + void TestCargoBikeParameters() throws Exception { + request.setProfile(APIEnums.Profile.CYCLING_CARGO); + + request.getRouteOptions().getProfileParams().setRestrictions(vehicleParams); + + RoutingRequest routingRequest = routingService.convertRouteRequest(request); + + WheelchairParameters params = (WheelchairParameters) routingRequest.getSearchParameters().getProfileParameters(); + assertEquals(WheelchairTypesEncoder.getSmoothnessType(APIEnums.SmoothnessTypes.SMOOTHNESS_GOOD), params.getSmoothnessType()); + assertEquals(3.0f, params.getMaximumIncline(), 0); + assertEquals(1.0f, params.getMaximumSlopedKerb(), 0); + assertEquals(2.0f, params.getMinimumWidth(), 0); + assertEquals(WheelchairTypesEncoder.getSurfaceType("asphalt"), params.getSurfaceType()); + assertTrue(params.isRequireSurfaceQualityKnown()); + assertTrue(params.allowUnsuitable()); + } + @Test void testBearings() throws StatusCodeException { request.setBearings(new Double[][]{{10.0, 10.0}, {260.0, 90.0}, {45.0, 30.0}}); diff --git a/ors-api/src/test/java/org/heigit/ors/apitests/routing/ParamsTest.java b/ors-api/src/test/java/org/heigit/ors/apitests/routing/ParamsTest.java index fbeea66d65..7b32437cc5 100644 --- a/ors-api/src/test/java/org/heigit/ors/apitests/routing/ParamsTest.java +++ b/ors-api/src/test/java/org/heigit/ors/apitests/routing/ParamsTest.java @@ -781,6 +781,7 @@ void expectCarToRejectWalkingAvoidables() { JSONObject options = new JSONObject(); JSONArray avoids = new JSONArray(); avoids.put("steps"); + avoids.put("junction"); avoids.put("fords"); options.put("avoid_features", avoids); diff --git a/ors-api/src/test/java/org/heigit/ors/apitests/services/RoutingServiceGreenTest.java b/ors-api/src/test/java/org/heigit/ors/apitests/services/RoutingServiceGreenTest.java new file mode 100644 index 0000000000..dc9d5bd966 --- /dev/null +++ b/ors-api/src/test/java/org/heigit/ors/apitests/services/RoutingServiceGreenTest.java @@ -0,0 +1,50 @@ +package org.heigit.ors.api.services; + +import org.heigit.ors.routing.RouteResult; +import org.heigit.ors.routing.APIEnums; +import org.locationtech.jts.geom.Coordinate; +import org.heigit.ors.api.EndpointsProperties; +import org.heigit.ors.api.requests.routing.RouteRequestOptions; +import org.heigit.ors.api.requests.routing.RequestProfileParams; +import org.heigit.ors.api.requests.routing.RequestProfileParamsWeightings; +import org.heigit.ors.api.requests.routing.RouteRequest; + +import org.junit.jupiter.api.Test; +class RoutingGreenTest { + + public RoutingGreenTest() throws Exception { + + } + @Test + void RoutingGreenTestCargo(){ + EndpointsProperties endpointsProperties = new EndpointsProperties(); + RoutingService routingService = new RoutingService(endpointsProperties); + Coordinate start = new Coordinate(8.650547, 49.400285); + Coordinate end = new Coordinate(9.121427,48.775995); + + try{ + RouteRequest request = new RouteRequest(start, end); + request.setProfile(APIEnums.Profile.CYCLING_CARGO); + + RouteRequestOptions options = new RouteRequestOptions(); + RequestProfileParams params = new RequestProfileParams(); + RequestProfileParamsWeightings weightings = new RequestProfileParamsWeightings(); + + weightings.setGreenIndex(0.5f); + weightings.setQuietIndex(0.2f); + weightings.setSteepnessDifficulty(3); + + params.setWeightings(weightings); + params.setSurfaceQualityKnown(true); + params.setAllowUnsuitable(true); + + options.setProfileParams(params); + request.setRouteOptions(options); + + RouteResult[] result = routingService.generateRouteFromRequest(request); + } catch (Exception e){ + int i = 7; + } + + } +} diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/AvoidFeatureFlags.java b/ors-engine/src/main/java/org/heigit/ors/routing/AvoidFeatureFlags.java index ec77cca7c6..c319a18125 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/AvoidFeatureFlags.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/AvoidFeatureFlags.java @@ -22,9 +22,10 @@ public class AvoidFeatureFlags { public static final int STEPS = 4; public static final int FERRIES = 8; public static final int FORDS = 16; + public static final int JUNCTION = 32; private static final int DRIVING_FEATURES = HIGHWAYS | TOLLWAYS | FERRIES | FORDS; - private static final int CYCLING_FEATURES = STEPS | FERRIES | FORDS; + private static final int CYCLING_FEATURES = STEPS | FERRIES | FORDS | JUNCTION; private static final int WALKING_FEATURES = STEPS | FERRIES | FORDS; private static final int WHEELCHAIR_FEATURES = WALKING_FEATURES; @@ -38,6 +39,7 @@ public static int getFromString(String value) { case "ferries" -> FERRIES; case "steps" -> STEPS; case "fords" -> FORDS; + case "junction" -> JUNCTION; default -> 0; }; } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfileType.java b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfileType.java index 5b6cac2288..151c682144 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfileType.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/RoutingProfileType.java @@ -33,6 +33,7 @@ public class RoutingProfileType { public static final int CYCLING_MOUNTAIN = 11; public static final int CYCLING_ROAD = 12; public static final int CYCLING_ELECTRIC = 17; + public static final int CYCLING_CARGO = 18; // WALKING STUFF public static final int FOOT_WALKING = 20; @@ -98,6 +99,7 @@ public static boolean isCycling(int routePref) { || routePref == CYCLING_MOUNTAIN || routePref == CYCLING_ROAD || routePref == CYCLING_ELECTRIC + || routePref == CYCLING_CARGO || routePref == GH_BIKE || routePref == GH_BIKE2 || routePref == GH_BIKE_MTB @@ -119,6 +121,7 @@ public static String getName(int profileType) { case CYCLING_MOUNTAIN -> "cycling-mountain"; case CYCLING_ROAD -> "cycling-road"; case CYCLING_ELECTRIC -> "cycling-electric"; + case CYCLING_CARGO -> "cycling-cargo"; case FOOT_WALKING -> "foot-walking"; case FOOT_HIKING -> "foot-hiking"; case FOOT_JOGGING -> "foot-jogging"; @@ -148,6 +151,7 @@ public static int getFromString(String profileType) { case "cycling-mountain" -> CYCLING_MOUNTAIN; case "cycling-road" -> CYCLING_ROAD; case "cycling-electric" -> CYCLING_ELECTRIC; + case "cycling-cargo" -> CYCLING_CARGO; case "foot-walking" -> FOOT_WALKING; case "foot-hiking" -> FOOT_HIKING; case "foot-jogging" -> FOOT_JOGGING; @@ -191,6 +195,7 @@ public static String getEncoderName(int routePref) { case RoutingProfileType.GH_FOOT -> FlagEncoderNames.GH_FOOT; case RoutingProfileType.GH_HIKE -> FlagEncoderNames.GH_HIKE; case RoutingProfileType.CYCLING_ELECTRIC -> FlagEncoderNames.BIKE_ELECTRO; + case RoutingProfileType.CYCLING_CARGO-> FlagEncoderNames.BIKE_CARGO; default -> FlagEncoderNames.UNKNOWN; }; } @@ -227,6 +232,7 @@ public static int getFromEncoderName(String encoder) { case FlagEncoderNames.GH_FOOT -> RoutingProfileType.FOOT_WALKING; case FlagEncoderNames.GH_HIKE -> RoutingProfileType.FOOT_HIKING; case FlagEncoderNames.BIKE_ELECTRO -> RoutingProfileType.CYCLING_ELECTRIC; + case FlagEncoderNames.BIKE_CARGO -> RoutingProfileType.CYCLING_CARGO; default -> RoutingProfileType.UNKNOWN; }; } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/JunctionType.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/JunctionType.java new file mode 100644 index 0000000000..80d7c85f66 --- /dev/null +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/JunctionType.java @@ -0,0 +1,62 @@ +/* This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ +package org.heigit.ors.routing.graphhopper.extensions; + +public class JunctionType { + + public static final int NONE = 0; + + // https://en.wikipedia.org/wiki/Vehicle_category + + public static final int M1 = 1; + public static final int M2 = 2; + public static final int M3 = 4; + public static final int M = M1 | M2 | M3; + + public static final int N1 = 8; + public static final int N2 = 16; + public static final int N3 = 32; + public static final int L1 = 64; // L1 = Electric Cycle + + public static final int N = N1 | N2 | N3; + + public static final int GENERAL = M | N | L1; + + // OSM classification + public static final int MOTORCAR = M1; + public static final int GOODS = N1; + public static final int HGV = N2 | N3; + + public static final int CYCLING_CARGO = L1; + + private JunctionType() { + } + + public static boolean isSet(int flag, int value) { + return (flag & value) == flag; + } + + public static boolean isType(int flag, int value) { + return (flag & value) != 0; + } + + public static boolean isMType(int value) { + return isType(M, value); + } + + public static boolean isNType(int value) { + return isType(N, value); + } + +} diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java index 5166faa8b7..3267c62061 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java @@ -57,6 +57,14 @@ public FlagEncoder createFlagEncoder(String name, PMap configuration) { } return new org.heigit.ors.routing.graphhopper.extensions.flagencoders.bike.ElectroBikeFlagEncoder(configuration); + case FlagEncoderNames.BIKE_CARGO: + // MARQ24 hardcoded "ignore" consider_elevation for the NextGenMountainBike FlagEncoder - when + // consider_elevation is enabled we have various detours (over smaler tracks) + if (configuration.getBool(KEY_CONSIDER_ELEVATION, false)) { + configuration.remove(KEY_CONSIDER_ELEVATION); + } + return new org.heigit.ors.routing.graphhopper.extensions.flagencoders.bike.CargoBikeFlagEncoder(configuration); + case FlagEncoderNames.ROADBIKE_ORS: // MARQ24 hardcoded "ignore" consider_elevation for the NextGenRoadbike FlagEncoder - when // consider_elevation is enabled we have various detours (over smaler tracks) diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java index 33a532137a..acabbe57ab 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/OSMTags.java @@ -33,6 +33,7 @@ private Keys() { public static final String JUNCTION = "junction"; public static final String RAILWAY = "railway"; public static final String MAN_MADE = "man_made"; + public static final String CYCLEWAY = "cycleway"; public static final String TUNNEL = "tunnel"; public static final String BICYCLE = "bicycle"; public static final String WATERWAY = "waterway"; diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidFeaturesEdgeFilter.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidFeaturesEdgeFilter.java index a613fabf29..e54dcc5b3e 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidFeaturesEdgeFilter.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidFeaturesEdgeFilter.java @@ -21,13 +21,17 @@ import org.heigit.ors.routing.RoutingProfileCategory; import org.heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils; import org.heigit.ors.routing.graphhopper.extensions.storages.TollwaysGraphStorage; +import org.heigit.ors.routing.graphhopper.extensions.storages.JunctionGraphStorage; import org.heigit.ors.routing.graphhopper.extensions.storages.WayCategoryGraphStorage; import org.heigit.ors.routing.pathprocessors.TollwayExtractor; +import org.heigit.ors.routing.pathprocessors.JunctionExtractor; + public class AvoidFeaturesEdgeFilter implements EdgeFilter { private final byte[] buffer; private final WayCategoryGraphStorage storage; private TollwayExtractor tollwayExtractor; + private JunctionExtractor junctionExtractor; private final int avoidFeatureType; private static final int NOT_TOLLWAYS = ~AvoidFeatureFlags.TOLLWAYS; @@ -45,6 +49,10 @@ public AvoidFeaturesEdgeFilter(int profileType, RouteSearchParameters searchPara TollwaysGraphStorage extTollways = GraphStorageUtils.getGraphExtension(graphStorage, TollwaysGraphStorage.class); if (extTollways != null) tollwayExtractor = new TollwayExtractor(extTollways, searchParams.getProfileType(), searchParams.getProfileParameters()); + + JunctionGraphStorage extJunction = GraphStorageUtils.getGraphExtension(graphStorage, JunctionGraphStorage.class); + if (extJunction != null) + junctionExtractor = new JunctionExtractor(extJunction, searchParams.getProfileType(), searchParams.getProfileParameters()); } public AvoidFeaturesEdgeFilter(int avoidFeatureType, GraphHopperStorage graphStorage) throws Exception { diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java index 7e2634f159..4ac5d1c78e 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java @@ -17,6 +17,7 @@ public class FlagEncoderNames { public static final String ROADBIKE_ORS = "roadbike" + ORS_SUFFIX; public static final String MTB_ORS = "mtb" + ORS_SUFFIX; public static final String BIKE_ELECTRO = "electrobike"; + public static final String BIKE_CARGO = "cargobike"; public static final String PEDESTRIAN_ORS = "pedestrian" + ORS_SUFFIX; public static final String HIKING_ORS = "hiking" + ORS_SUFFIX; diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CargoBikeFlagEncoder.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CargoBikeFlagEncoder.java new file mode 100644 index 0000000000..f6282adc37 --- /dev/null +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CargoBikeFlagEncoder.java @@ -0,0 +1,118 @@ +/* This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ +package org.heigit.ors.routing.graphhopper.extensions.flagencoders.bike; + +import com.graphhopper.util.PMap; +import org.heigit.ors.routing.graphhopper.extensions.flagencoders.FlagEncoderNames; + +public class CargoBikeFlagEncoder extends CommonBikeFlagEncoder { + private static final int MEAN_SPEED = 20; + + public CargoBikeFlagEncoder(PMap properties) { + this((int) properties.getLong("speed_bits", 4) + (properties.getBool("consider_elevation", false) ? 1 : 0), + properties.getLong("speed_factor", 2), + properties.getBool("turn_costs", false) ? 1 : 0, properties.getBool("consider_elevation", false)); + setProperties(properties); + } + + public CargoBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts, boolean considerElevation) { + super(speedBits, speedFactor, maxTurnCosts, considerElevation); + + + setTrackTypeSpeed("grade1", 21); // paved + setTrackTypeSpeed("grade2", 15); // now unpaved ... + setTrackTypeSpeed("grade3", 9); + setTrackTypeSpeed("grade4", 7); + setTrackTypeSpeed("grade5", 4); // like sand/grass + + setSurfaceSpeed("paved", 21); + setSurfaceSpeed("asphalt", 21); + setSurfaceSpeed("cobblestone", 9); + setSurfaceSpeed("cobblestone:flattened", 11); + setSurfaceSpeed("sett", 11); + setSurfaceSpeed("concrete", 21); + setSurfaceSpeed("concrete:lanes", 18); + setSurfaceSpeed("concrete:plates", 18); + setSurfaceSpeed("paving_stones", 13); + setSurfaceSpeed("paving_stones:30", 13); + setSurfaceSpeed("unpaved", 15); + setSurfaceSpeed("compacted", 17); + setSurfaceSpeed("dirt", 11); + setSurfaceSpeed("earth", 13); + setSurfaceSpeed("fine_gravel", 19); + setSurfaceSpeed("grass", 9); + setSurfaceSpeed("grass_paver", 9); + setSurfaceSpeed("gravel", 13); + setSurfaceSpeed("ground", 13); + setSurfaceSpeed("ice", PUSHING_SECTION_SPEED / 2); + setSurfaceSpeed("metal", 11); + setSurfaceSpeed("mud", 11); + setSurfaceSpeed("pebblestone", 18); + setSurfaceSpeed("salt", 7); + setSurfaceSpeed("sand", 7); + setSurfaceSpeed("wood", 7); + + setHighwaySpeed("living_street", 9); + setHighwaySpeed("steps", PUSHING_SECTION_SPEED / 2); + setHighwaySpeed("cycleway", 21); + setHighwaySpeed("path", 13); + setHighwaySpeed("footway", 7); + setHighwaySpeed("pedestrian", 7); + setHighwaySpeed("road", 14); + setHighwaySpeed("track", 13); + setHighwaySpeed("service", 15); + setHighwaySpeed("unclassified", 18); + setHighwaySpeed("residential", 21); + + setHighwaySpeed("trunk", 20); + setHighwaySpeed("trunk_link", 20); + setHighwaySpeed("primary", 21); + setHighwaySpeed("primary_link", 21); + setHighwaySpeed("secondary", 21); + setHighwaySpeed("secondary_link", 21); + setHighwaySpeed("tertiary", 21); + setHighwaySpeed("tertiary_link", 21); + + addPushingSection("path"); + addPushingSection("footway"); + addPushingSection("pedestrian"); + addPushingSection("steps"); + + avoidHighwayTags.add("trunk"); + avoidHighwayTags.add("trunk_link"); + avoidHighwayTags.add("primary"); + avoidHighwayTags.add("primary_link"); + avoidHighwayTags.add("secondary"); + avoidHighwayTags.add("secondary_link"); + + + blockByDefaultBarriers.add("kissing_gate"); + + setSpecificClassBicycle("touring"); + } + + public double getMeanSpeed() { + return MEAN_SPEED; + } + + @Override + protected double getDownhillMaxSpeed() { + return 30; + } + + @Override + public String toString() { + return FlagEncoderNames.BIKE_CARGO; + } +} diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/JunctionGraphStorage.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/JunctionGraphStorage.java new file mode 100644 index 0000000000..4c8ec02ecc --- /dev/null +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/JunctionGraphStorage.java @@ -0,0 +1,115 @@ +package org.heigit.ors.routing.graphhopper.extensions.storages; + +import com.graphhopper.storage.DataAccess; +import com.graphhopper.storage.Directory; +import com.graphhopper.storage.Graph; +import com.graphhopper.storage.GraphExtension; + +public class JunctionGraphStorage implements GraphExtension { + /* pointer for no entry */ + protected final int efJunction; + + protected DataAccess junctionEdges; + protected int junctionEdgeEntryIndex = 5; + protected int junctionEdgeEntryBytes; + protected int junctionEdgesCount; + + public JunctionGraphStorage() { + efJunction = nextJunctionBlockEntryIndex(1); + + junctionEdgeEntryBytes = junctionEdgeEntryIndex; + junctionEdgesCount = 0; + } + + public void init(Graph graph, Directory dir) { + if (junctionEdgesCount > 0) + throw new AssertionError("The ext_junction storage must be initialized only once."); + + this.junctionEdges = dir.find("ext_junction"); + } + + protected final int nextJunctionBlockEntryIndex(int size) { + int res = junctionEdgeEntryIndex; + junctionEdgeEntryIndex += size; + return res; + } + + public void setJunctionSegmentSize(int bytes) { + junctionEdges.setSegmentSize(bytes); + } + + public JunctionGraphStorage create(long initBytes) { + junctionEdges.create(initBytes * junctionEdgeEntryBytes); + return this; + } + + public void flush() { + junctionEdges.setHeader(0, junctionEdgeEntryBytes); + junctionEdges.setHeader(4, junctionEdgesCount); + junctionEdges.flush(); + } + + public void close() { + junctionEdges.close(); + } + + @Override + public long getCapacity() { + return junctionEdges.getCapacity(); + } + + public int entries() { + return junctionEdgesCount; + } + + public boolean loadExisting() { + if (!junctionEdges.loadExisting()) + throw new IllegalStateException("Unable to load storage 'ext_junction'. Corrupt file or directory?"); + + junctionEdgeEntryBytes = junctionEdges.getHeader(0); + junctionEdgesCount = junctionEdges.getHeader(4); + return true; + } + + void ensureJunctionEdgesIndex(int edgeIndex) { + junctionEdges.ensureCapacity(((long) edgeIndex + 1) * junctionEdgeEntryBytes); + } + + public void setJunctionEdgeValue(int edgeId, int value) { + junctionEdgesCount++; + ensureJunctionEdgesIndex(edgeId); + + byte byteValue = (byte) value; + + junctionEdges.setByte((long) edgeId * junctionEdgeEntryBytes + efJunction, byteValue); + } + + public int getJunctionEdgeValue(int edgeId) { + byte byteValue = junctionEdges.getByte((long) edgeId * junctionEdgeEntryBytes + efJunction); + return byteValue & 0xFF; + } + + public boolean isRequireNodeField() { + return true; + } + + public boolean isRequireEdgeField() { + // we require the additional field in the graph to point to the first + // entry in the node table + return true; + } + + public int getDefaultNodeFieldValue() { + return -1; + } + + public int getDefaultEdgeFieldValue() { + return -1; + } + + @Override + public boolean isClosed() { + return false; + } +} + diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilder.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilder.java new file mode 100644 index 0000000000..dc3517e98b --- /dev/null +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilder.java @@ -0,0 +1,93 @@ +/* This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ +package org.heigit.ors.routing.graphhopper.extensions.storages.builders; + +import com.graphhopper.GraphHopper; +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.storage.GraphExtension; +import com.graphhopper.util.EdgeIteratorState; +import org.heigit.ors.routing.graphhopper.extensions.JunctionType; +import org.heigit.ors.routing.graphhopper.extensions.storages.JunctionGraphStorage; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class JunctionGraphStorageBuilder extends AbstractGraphStorageBuilder { + private JunctionGraphStorage storage; + private int junction; + private final List junctionTags = new ArrayList<>(6); + + public JunctionGraphStorageBuilder() { + // Eventually add more junction tags, e.g. "junction=roundabout" + junctionTags.addAll(Arrays.asList("junction")); + } + + public GraphExtension init(GraphHopper graphhopper) throws Exception { + if (storage != null) + throw new Exception("GraphStorageBuilder has been already initialized."); + + storage = new JunctionGraphStorage(); + + return storage; + } + + public void processWay(ReaderWay way) { + junction = JunctionType.NONE; + + for (String key : junctionTags) { + if (way.hasTag(key)) { + String value = way.getTag(key); + + if (value != null) { + switch (key) { + case "junction" -> setFlag(JunctionType.CYCLING_CARGO, value); + // case "toll:hgv" -> setFlag(JunctionType.HGV, value); + // case "toll:N1" -> //currently not used in OSM + // setFlag(JunctionType.N1, value); + // case "toll:N2" -> setFlag(JunctionType.N2, value); + // case "toll:N3" -> setFlag(JunctionType.N3, value); + // case "toll:motorcar" -> setFlag(JunctionType.MOTORCAR, value); + default -> { + } + } + } + } + } + + } + + private void setFlag(int flag, String value) { + switch (value) { + case "yes" -> junction |= flag; + case "no" -> junction &= ~flag; + default -> { + } + } + } + + public void processEdge(ReaderWay way, EdgeIteratorState edge) { + storage.setJunctionEdgeValue(edge.getEdge(), junction); + } + + @Override + public String getName() { + return "junction"; + } + + // Added getter method to access the junction attribute + public int getCurrentJunctionValue() { + return this.junction; + } +} diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java index 6abf034eaf..d9661df50c 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java @@ -66,6 +66,8 @@ public void processWay(ReaderWay way) { wayType |= AvoidFeatureFlags.HIGHWAYS; } else if (value.equals("steps")) { wayType |= AvoidFeatureFlags.STEPS; + } else if (value.equals("junction")) { + wayType |= AvoidFeatureFlags.JUNCTION; } } else if (value.equals("yes") && key.startsWith("toll")) { wayType |= AvoidFeatureFlags.TOLLWAYS; @@ -73,6 +75,8 @@ public void processWay(ReaderWay way) { wayType |= AvoidFeatureFlags.FERRIES; } else if (("ford".equals(key) && value.equals("yes"))) { wayType |= AvoidFeatureFlags.FORDS; + } else if (("junction".equals(key) && value.equals("yes"))) { + wayType |= AvoidFeatureFlags.JUNCTION; } } } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/pathprocessors/JunctionExtractor.java b/ors-engine/src/main/java/org/heigit/ors/routing/pathprocessors/JunctionExtractor.java new file mode 100644 index 0000000000..f61ed84c89 --- /dev/null +++ b/ors-engine/src/main/java/org/heigit/ors/routing/pathprocessors/JunctionExtractor.java @@ -0,0 +1,81 @@ +/* This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ +package org.heigit.ors.routing.pathprocessors; + +import org.heigit.ors.routing.RoutingProfileType; +import org.heigit.ors.routing.graphhopper.extensions.HeavyVehicleAttributes; +import org.heigit.ors.routing.graphhopper.extensions.JunctionType; +import org.heigit.ors.routing.graphhopper.extensions.storages.JunctionGraphStorage; +import org.heigit.ors.routing.parameters.ProfileParameters; +import org.heigit.ors.routing.parameters.VehicleParameters; + +public class JunctionExtractor { + private VehicleParameters vehicleParams; + private final int profileType; + private final JunctionGraphStorage storage; + + public JunctionExtractor(JunctionGraphStorage storage, int profileType, ProfileParameters vehicleParams) { + this.storage = storage; + this.profileType = profileType; + if (vehicleParams instanceof VehicleParameters parameters) + this.vehicleParams = parameters; + } + + /** + * return if a way is a tollway for the configured vehicle. + * + * @param edgeId The edgeId for which toll should be checked + * @see HeavyVehicleAttributes + */ + public int getValue(int edgeId) { + int value = storage.getJunctionEdgeValue(edgeId); + + switch (value) { + // toll=no + case JunctionType.NONE: + return 0; + // toll=yes + case JunctionType.GENERAL: + return 1; + default: + switch (profileType) { + // toll:motorcar + case RoutingProfileType.DRIVING_CAR: + return JunctionType.isSet(JunctionType.MOTORCAR, value) ? 1 : 0; + + case RoutingProfileType.DRIVING_HGV: + // toll:hgv + if (JunctionType.isSet(JunctionType.HGV, value)) + return 1; + + // check for weight specific toll tags even when weight is unset + double weight = vehicleParams == null ? 0 : vehicleParams.getWeight(); + if ((weight == 0 && JunctionType.isNType(value)) + || (weight < 3.5 && JunctionType.isSet(JunctionType.N1, value)) + || (weight >= 3.5 && weight < 12 && JunctionType.isSet(JunctionType.N2, value)) + || (weight >= 12 && JunctionType.isSet(JunctionType.N3, value))) + return 1; + return 0; + default: + return 0; + + case RoutingProfileType.CYCLING_CARGO, RoutingProfileType.CYCLING_ELECTRIC: + return JunctionType.isSet(JunctionType.CYCLING_CARGO, value) ? 1 : 0; + + } + } + + } + +} diff --git a/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CargoBikeFlagEncoderTest.java b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CargoBikeFlagEncoderTest.java new file mode 100644 index 0000000000..5c91bcbd44 --- /dev/null +++ b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CargoBikeFlagEncoderTest.java @@ -0,0 +1,54 @@ +package org.heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.routing.util.EncodingManager; +import org.heigit.ors.routing.graphhopper.extensions.ORSDefaultFlagEncoderFactory; +import org.heigit.ors.routing.graphhopper.extensions.flagencoders.bike.CargoBikeFlagEncoder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CargoBikeFlagEncoderTest { + + protected final Set preferHighwayTags = new HashSet<>(); + private final CargoBikeFlagEncoder flagEncoder; + private ReaderWay way; + + + + public CargoBikeFlagEncoderTest() { + EncodingManager encodingManager = EncodingManager.create(new ORSDefaultFlagEncoderFactory(), FlagEncoderNames.BIKE_CARGO); + flagEncoder = (CargoBikeFlagEncoder) encodingManager.getEncoder(FlagEncoderNames.BIKE_CARGO); + } + + @BeforeEach + void initWay() { + way = new ReaderWay(1); + } + + @Test + void acceptBridlewayOnlyWithBicycleTag() { + way.setTag("highway", "bridleway"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + way.setTag("bicycle", "yes"); + assertTrue(flagEncoder.getAccess(way).isWay()); + + way.setTag("bicycle", "no"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + } + + @Test + void checkTagAvailability() { + way.setTag("cycleway", "lane"); + assertTrue(flagEncoder.getAccess(way).isWay()); + + preferHighwayTags.add("cycleway"); + preferHighwayTags.contains("cycleway"); + assertTrue(preferHighwayTags.contains("cycleway")); + } +} diff --git a/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilderTest.java b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilderTest.java new file mode 100644 index 0000000000..a57356ae45 --- /dev/null +++ b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/storages/builders/JunctionGraphStorageBuilderTest.java @@ -0,0 +1,41 @@ +package org.heigit.ors.routing.graphhopper.extensions.storages.builders; + +import com.graphhopper.reader.ReaderWay; +import org.heigit.ors.routing.graphhopper.extensions.JunctionType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class JunctionGraphStorageBuilderTest { + private JunctionGraphStorageBuilder builder; + + public JunctionGraphStorageBuilderTest() { + builder = new JunctionGraphStorageBuilder(); + } + + @BeforeEach + void reset() { + builder = new JunctionGraphStorageBuilder(); + } + + @Test + void testProcessWayWithJunctionTagYes() { + ReaderWay way = new ReaderWay(1); + way.setTag("junction", "yes"); + + builder.processWay(way); + + assertEquals(JunctionType.CYCLING_CARGO, builder.getCurrentJunctionValue()); + } + + @Test + void testProcessWayWithJunctionTagNo() { + ReaderWay way = new ReaderWay(1); + way.setTag("junction", "no"); + + builder.processWay(way); + + assertEquals(JunctionType.NONE, builder.getCurrentJunctionValue()); + } +}