diff --git a/CHANGELOG.md b/CHANGELOG.md index d27a7eb8b2..4e93df4d82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ RELEASING: - NPE in error handling ([#1925](https://github.com/GIScience/openrouteservice/pull/1925)) - Add missing 'build' in documentation for profile properties ([#1947](https://github.com/GIScience/openrouteservice/issues//1947)) +- Allow vehicles on ferries without explicit access tags ([#1954](https://github.com/GIScience/openrouteservice/pull/1954)) ### Security diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java index 682b583efe..4f3af7a295 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java @@ -81,11 +81,14 @@ public EncodingManager.Access getAccess(ReaderWay way) { for (String restrictionValue : restrictionValues) { if (restrictedValues.contains(restrictionValue)) return EncodingManager.Access.CAN_SKIP; - if (intendedValues.contains(restrictionValue) || - // implied default is allowed only if foot and bicycle is not specified: - restrictionValue.isEmpty() && !way.hasTag("foot") && !way.hasTag("bicycle")) + if (intendedValues.contains(restrictionValue)) return EncodingManager.Access.FERRY; } + + // implied default is allowed only if foot and bicycle is not specified: + if (restrictionValues.length == 0 && !way.hasTag("foot") && !way.hasTag("bicycle")) { + return EncodingManager.Access.FERRY; + } } return EncodingManager.Access.CAN_SKIP; } diff --git a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java index 103d59dcea..abf96a25ae 100644 --- a/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java +++ b/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java @@ -162,11 +162,13 @@ public EncodingManager.Access getAccess(ReaderWay way) { for (String restrictionValue : restrictionValues) { if (restrictedValues.contains(restrictionValue)) return EncodingManager.Access.CAN_SKIP; - if (intendedValues.contains(restrictionValue) || - // implied default is allowed only if foot and bicycle is not specified: - restrictionValue.isEmpty() && !way.hasTag("foot") && !way.hasTag("bicycle")) + if (intendedValues.contains(restrictionValue)) return EncodingManager.Access.FERRY; } + // implied default is allowed only if foot and bicycle is not specified: + if (restrictionValues.length == 0 && !way.hasTag("foot") && !way.hasTag("bicycle")) { + return EncodingManager.Access.FERRY; + } } return EncodingManager.Access.CAN_SKIP; } diff --git a/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoderTest.java b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoderTest.java index e8a25742f2..9f7f638648 100644 --- a/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoderTest.java +++ b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoderTest.java @@ -41,6 +41,10 @@ Weighting createWeighting(String vehicle, String weighting) { return weightingFactory.createWeighting(profile, new PMap(), false); } + private ReaderWay generateFerryWay() { + way.getTags().put("route", "ferry"); + return way; + } @Test void testDestinationTag() { IntsRef relFlags = em.createRelationFlags(); @@ -67,4 +71,26 @@ void testDestinationTag() { assertEquals(WAY_DISTANCE * LimitedAccessWeighting.VEHICLE_DESTINATION_FACTOR, carShortest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); assertEquals(WAY_DISTANCE * LimitedAccessWeighting.DEFAULT_DESTINATION_FACTOR, bikeShortest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); } + + @Test + void testFerryTag() { + way = generateFerryWay(); + CarFlagEncoder flagEncoder = (CarFlagEncoder) em.getEncoder(FlagEncoderNames.CAR_ORS); + // motor_vehicle = no -> reject + way.getTags().put("motor_vehicle", "no"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + // foot = * -> reject + way.getTags().remove("motor_vehicle"); + way.getTags().put("foot", "no"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + way.getTags().replace("foot", "yes"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + // only ferry flag -> accept + way.getTags().remove("foot"); + assertTrue(flagEncoder.getAccess(way).isFerry()); + } + } diff --git a/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoderTest.java b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoderTest.java new file mode 100644 index 0000000000..bcddc565b0 --- /dev/null +++ b/ors-engine/src/test/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoderTest.java @@ -0,0 +1,96 @@ +package org.heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.config.Profile; +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.routing.WeightingFactory; +import com.graphhopper.routing.util.EncodingManager; +import com.graphhopper.routing.weighting.Weighting; +import com.graphhopper.storage.GraphBuilder; +import com.graphhopper.storage.GraphHopperStorage; +import com.graphhopper.storage.IntsRef; +import com.graphhopper.util.GHUtility; +import com.graphhopper.util.PMap; +import org.heigit.ors.routing.graphhopper.extensions.ORSDefaultFlagEncoderFactory; +import org.heigit.ors.routing.graphhopper.extensions.ORSWeightingFactory; +import org.heigit.ors.routing.graphhopper.extensions.weighting.LimitedAccessWeighting; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class HeavyVehicleFlagEncoderTest { + private final EncodingManager em = EncodingManager.create(new ORSDefaultFlagEncoderFactory(), FlagEncoderNames.HEAVYVEHICLE + "," + FlagEncoderNames.BIKE_ORS); + private ReaderWay way; + + static final double WAY_DISTANCE = 1000; + static final double HEAVYVEHICLE_DURATION = 180; + static final double BIKE_DURATION = 300; + + @BeforeEach + void initWay() { + way = new ReaderWay(1); + } + + Weighting createWeighting(String vehicle, String weighting) { + GraphHopperStorage g = new GraphBuilder(em).create(); + WeightingFactory weightingFactory = new ORSWeightingFactory(g, em); + + Profile profile = new Profile(vehicle + "_" + weighting).setVehicle(vehicle).setWeighting(weighting); + + return weightingFactory.createWeighting(profile, new PMap(), false); + } + + private ReaderWay generateFerryWay() { + way.getTags().put("route", "ferry"); + return way; + } + @Test + void testDestinationTag() { + IntsRef relFlags = em.createRelationFlags(); + + Weighting hgvFastest = createWeighting(FlagEncoderNames.HEAVYVEHICLE, "fastest"); + Weighting bikeFastest = createWeighting(FlagEncoderNames.BIKE_ORS, "fastest"); + + way.setTag("highway", "road"); + EncodingManager.AcceptWay acceptWay = new EncodingManager.AcceptWay(); + assertTrue(em.acceptWay(way, acceptWay)); + IntsRef edgeFlags = em.handleWayTags(way, acceptWay, relFlags); + assertEquals(HEAVYVEHICLE_DURATION, hgvFastest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + assertEquals(BIKE_DURATION, bikeFastest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + + way.setTag("motor_vehicle", "destination"); + edgeFlags = em.handleWayTags(way, acceptWay, relFlags); + assertEquals(HEAVYVEHICLE_DURATION * LimitedAccessWeighting.VEHICLE_DESTINATION_FACTOR, hgvFastest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + assertEquals(BIKE_DURATION * LimitedAccessWeighting.DEFAULT_DESTINATION_FACTOR, bikeFastest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + + Weighting carShortest = createWeighting(FlagEncoderNames.HEAVYVEHICLE, "shortest"); + Weighting bikeShortest = createWeighting(FlagEncoderNames.BIKE_ORS, "shortest"); + + edgeFlags = em.handleWayTags(way, acceptWay, relFlags); + assertEquals(WAY_DISTANCE * LimitedAccessWeighting.VEHICLE_DESTINATION_FACTOR, carShortest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + assertEquals(WAY_DISTANCE * LimitedAccessWeighting.DEFAULT_DESTINATION_FACTOR, bikeShortest.calcEdgeWeight(GHUtility.createMockedEdgeIteratorState(WAY_DISTANCE, edgeFlags), false), 0.1); + } + + @Test + void testFerryTag() { + way = generateFerryWay(); + HeavyVehicleFlagEncoder flagEncoder = (HeavyVehicleFlagEncoder) em.getEncoder(FlagEncoderNames.HEAVYVEHICLE); + // motor_vehicle = no -> reject + way.getTags().put("motor_vehicle", "no"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + // foot = * -> reject + way.getTags().remove("motor_vehicle"); + way.getTags().put("foot", "no"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + way.getTags().replace("foot", "yes"); + assertTrue(flagEncoder.getAccess(way).canSkip()); + + // only ferry flag -> accept + way.getTags().remove("foot"); + assertTrue(flagEncoder.getAccess(way).isFerry()); + } + +} \ No newline at end of file