diff --git a/.github/workflows/cibuild.yml b/.github/workflows/cibuild.yml index 1412ffc1ebf..e0fff032fdc 100644 --- a/.github/workflows/cibuild.yml +++ b/.github/workflows/cibuild.yml @@ -9,6 +9,7 @@ on: - master - dev-1.x - dev-2.x + - mfdz-park-and-ride pull_request: branches: - master @@ -44,7 +45,7 @@ jobs: files: target/site/jacoco/jacoco.xml - name: Publish to Dockerhub - if: ${{ github.repository_owner == 'mfdz' && github.ref == 'refs/heads/dev-2.x' }} + if: ${{ github.repository_owner == 'mfdz' && github.ref == 'refs/heads/mfdz-park-and-ride' }} uses: elgohr/Publish-Docker-Github-Action@master with: name: mfdz/opentripplanner diff --git a/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java b/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java index c857243c023..786d7fb7019 100644 --- a/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java +++ b/src/main/java/org/opentripplanner/api/parameter/QualifiedModeSet.java @@ -124,11 +124,9 @@ public RequestModes getRequestModes() { accessMode = StreetMode.CAR_TO_PARK; transferMode = StreetMode.WALK; egressMode = StreetMode.WALK; - if(transitModes.isEmpty()) { - directMode = StreetMode.CAR_TO_PARK; - } else { - directMode = StreetMode.BIKE; - } + // CAR_TO_PARK is quite expensive to compute, so we only use it if there are no + // transit modes + directMode = transitModes.isEmpty() ? StreetMode.CAR_TO_PARK : StreetMode.BIKE; } else if (requestMode.qualifiers.contains(Qualifier.PICKUP)) { accessMode = StreetMode.WALK; transferMode = StreetMode.WALK; diff --git a/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java b/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java index 9dea06e087a..2de7573457b 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/NearbyStopFinder.java @@ -4,7 +4,11 @@ import com.beust.jcommander.internal.Sets; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; +import java.util.List; +import java.util.Set; import org.locationtech.jts.geom.Coordinate; import org.opentripplanner.common.MinMap; import org.opentripplanner.ext.flex.trip.FlexTrip; @@ -13,9 +17,14 @@ import org.opentripplanner.model.StopLocation; import org.opentripplanner.model.TripPattern; import org.opentripplanner.routing.algorithm.astar.AStar; +import org.opentripplanner.routing.algorithm.astar.strategies.BikeToStopSkipEdgeStrategy; +import org.opentripplanner.routing.algorithm.astar.strategies.ComposingSkipEdgeStrategy; import org.opentripplanner.routing.algorithm.astar.strategies.DurationSkipEdgeStrategy; +import org.opentripplanner.routing.algorithm.astar.strategies.SkipEdgeStrategy; import org.opentripplanner.routing.algorithm.astar.strategies.TrivialRemainingWeightHeuristic; +import org.opentripplanner.routing.algorithm.astar.strategies.VehicleToStopSkipEdgeStrategy; import org.opentripplanner.routing.api.request.RoutingRequest; +import org.opentripplanner.routing.api.request.StreetMode; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.core.TraverseMode; import org.opentripplanner.routing.edgetype.StreetEdge; @@ -30,13 +39,6 @@ import org.opentripplanner.routing.vertextype.StreetVertex; import org.opentripplanner.routing.vertextype.TransitStopVertex; import org.opentripplanner.util.OTPFeature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; /** * These library functions are used by the streetless and streetful stop linkers, and in profile transfer generation. @@ -49,14 +51,13 @@ */ public class NearbyStopFinder { - private static final Logger LOG = LoggerFactory.getLogger(NearbyStopFinder.class); - public final boolean useStreets; private final Graph graph; private final double durationLimitInSeconds; private DirectGraphFinder directGraphFinder; + /** * Construct a NearbyStopFinder for the given graph and search radius, choosing whether to search via the street * network or straight line distance based on the presence of OSM street data in the graph. @@ -188,7 +189,9 @@ public List findNearbyStopsViaStreets ( routingRequest.dominanceFunction = new DominanceFunction.MinimumWeight(); var astar = new AStar(); - astar.setSkipEdgeStrategy(new DurationSkipEdgeStrategy(durationLimitInSeconds)); + var skipEdgeStrategy = getSkipEdgeStrategy(reverseDirection, routingRequest); + astar.setSkipEdgeStrategy(skipEdgeStrategy); + ShortestPathTree spt = astar.getShortestPathTree(routingRequest); // Only used if OTPFeature.FlexRouting.isOn() @@ -241,18 +244,34 @@ public List findNearbyStopsViaStreets ( return stopsFound; } - public List findNearbyStopsViaStreets ( - Set originVertices, - boolean reverseDirection, - boolean removeTempEdges + private SkipEdgeStrategy getSkipEdgeStrategy( + boolean reverseDirection, + RoutingRequest routingRequest ) { - RoutingRequest routingRequest = new RoutingRequest(TraverseMode.WALK); - return findNearbyStopsViaStreets( - originVertices, - reverseDirection, - removeTempEdges, - routingRequest - ); + var durationSkipEdgeStrategy = new DurationSkipEdgeStrategy(durationLimitInSeconds); + + // if we compute the accesses for Park+Ride, Bike+Ride and Bike+Transit we don't want to + // search the full durationLimit as this returns way too many stops. + // this is both slow and returns suboptimal results as it favours long drives with short + // transit legs. + // therefore, we use a heuristic based on the number of routes and their mode to determine + // what are "good" stops for those accesses. if we have reached a threshold of "good" stops + // we stop the access search. + if (!reverseDirection + && OTPFeature.VehicleToStopHeuristics.isOn() + && VehicleToStopSkipEdgeStrategy.applicableModes.contains( + routingRequest.modes.accessMode)) { + var strategy = new VehicleToStopSkipEdgeStrategy(graph.index::getRoutesForStop); + return new ComposingSkipEdgeStrategy(strategy, durationSkipEdgeStrategy); + } + else if (OTPFeature.VehicleToStopHeuristics.isOn() + && routingRequest.modes.accessMode == StreetMode.BIKE) { + var strategy = new BikeToStopSkipEdgeStrategy(graph.index::getTripsForStop); + return new ComposingSkipEdgeStrategy(strategy, durationSkipEdgeStrategy); + } + else { + return durationSkipEdgeStrategy; + } } private boolean canBoardFlex(State state, boolean reverse) { diff --git a/src/main/java/org/opentripplanner/model/TransitMode.java b/src/main/java/org/opentripplanner/model/TransitMode.java index 2e2e607bcda..12c0a7029c4 100644 --- a/src/main/java/org/opentripplanner/model/TransitMode.java +++ b/src/main/java/org/opentripplanner/model/TransitMode.java @@ -1,9 +1,7 @@ package org.opentripplanner.model; -import java.util.Arrays; import java.util.EnumSet; import java.util.Set; -import java.util.stream.Collectors; /** * Equivalent to GTFS route_type or to NeTEx TransportMode. diff --git a/src/main/java/org/opentripplanner/routing/algorithm/astar/AStar.java b/src/main/java/org/opentripplanner/routing/algorithm/astar/AStar.java index bded71ccf4b..20be20621c4 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/astar/AStar.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/astar/AStar.java @@ -52,8 +52,8 @@ class RunState { public int nVisited; public List targetAcceptedStates; public RunStatus status; - private RoutingRequest options; - private SearchTerminationStrategy terminationStrategy; + private final RoutingRequest options; + private final SearchTerminationStrategy terminationStrategy; public Vertex u_vertex; public RunState(RoutingRequest options, SearchTerminationStrategy terminationStrategy) { @@ -164,7 +164,8 @@ boolean iterate(){ runState.rctx.fromVertices, runState.rctx.toVertices, runState.u, - edge,runState.spt, + edge, + runState.spt, runState.options ) ) { diff --git a/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/BikeToStopSkipEdgeStrategy.java b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/BikeToStopSkipEdgeStrategy.java new file mode 100644 index 00000000000..fb6fe8ede3a --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/BikeToStopSkipEdgeStrategy.java @@ -0,0 +1,65 @@ +package org.opentripplanner.routing.algorithm.astar.strategies; + +import java.util.Collection; +import java.util.Set; +import java.util.function.Function; +import org.opentripplanner.model.BikeAccess; +import org.opentripplanner.model.Stop; +import org.opentripplanner.model.Trip; +import org.opentripplanner.routing.api.request.RoutingRequest; +import org.opentripplanner.routing.core.State; +import org.opentripplanner.routing.graph.Edge; +import org.opentripplanner.routing.graph.Vertex; +import org.opentripplanner.routing.spt.ShortestPathTree; +import org.opentripplanner.routing.vertextype.TransitStopVertex; + +/** + * When wanting to take a bike onto transit we want to improve the performance by limiting the + * number of accesses to those stops which actually have trips where you can take the bike on. + * Once we have reached enough of trips we skip all further edges. + */ +public class BikeToStopSkipEdgeStrategy + implements SkipEdgeStrategy { + + private static final int LIMIT = 100; + private static final double MAX_FACTOR = 1.2; + + private final Function> getTripsForStop; + + int numberOfBikeableTripsReached = 0; + double distanceLimit = Double.MAX_VALUE; + + public BikeToStopSkipEdgeStrategy(Function> getTripsForStop) { + this.getTripsForStop = getTripsForStop; + } + + @Override + public boolean shouldSkipEdge( + Set origins, + Set targets, + State current, + Edge edge, + ShortestPathTree spt, + RoutingRequest traverseOptions + ) { + if (current.getVertex() instanceof TransitStopVertex && distanceLimit == Double.MAX_VALUE) { + var stopVertex = (TransitStopVertex) current.getVertex(); + var stop = stopVertex.getStop(); + numberOfBikeableTripsReached += getTripsForStop.apply(stop).stream().filter( + BikeToStopSkipEdgeStrategy::bikeAccessForTrip).count(); + if (numberOfBikeableTripsReached >= LIMIT) { + distanceLimit = current.getWalkDistance() * MAX_FACTOR; + } + } + return current.getWalkDistance() > distanceLimit; + } + + + public static boolean bikeAccessForTrip(Trip trip) { + if (trip.getBikesAllowed() != BikeAccess.UNKNOWN) { + return trip.getBikesAllowed() == BikeAccess.ALLOWED; + } + + return trip.getRoute().getBikesAllowed() == BikeAccess.ALLOWED; + } +} diff --git a/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/ComposingSkipEdgeStrategy.java b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/ComposingSkipEdgeStrategy.java new file mode 100644 index 00000000000..a59500270f2 --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/ComposingSkipEdgeStrategy.java @@ -0,0 +1,40 @@ +package org.opentripplanner.routing.algorithm.astar.strategies; + +import java.util.Set; +import org.opentripplanner.routing.api.request.RoutingRequest; +import org.opentripplanner.routing.core.State; +import org.opentripplanner.routing.graph.Edge; +import org.opentripplanner.routing.graph.Vertex; +import org.opentripplanner.routing.spt.ShortestPathTree; + +/** + * Use several strategies in composition with each other, for example by limiting by time and number + * of stops visited. Only one needs to be skipped in order for {@link + * ComposingSkipEdgeStrategy#shouldSkipEdge(Set, Set, State, Edge, ShortestPathTree, + * RoutingRequest)} to return null. + */ +public class ComposingSkipEdgeStrategy implements SkipEdgeStrategy { + + final SkipEdgeStrategy[] strategies; + + public ComposingSkipEdgeStrategy(SkipEdgeStrategy... strategies) { + this.strategies = strategies; + } + + @Override + public boolean shouldSkipEdge( + Set origins, + Set targets, + State current, + Edge edge, + ShortestPathTree spt, + RoutingRequest traverseOptions + ) { + for (var strategy : strategies) { + if (strategy.shouldSkipEdge(origins, targets, current, edge, spt, traverseOptions)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/EuclideanRemainingWeightHeuristic.java b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/EuclideanRemainingWeightHeuristic.java index dacecb36513..b21bfb3fe46 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/EuclideanRemainingWeightHeuristic.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/EuclideanRemainingWeightHeuristic.java @@ -4,6 +4,7 @@ import org.opentripplanner.common.geometry.SphericalDistanceLibrary; import org.opentripplanner.routing.api.request.RoutingRequest; import org.opentripplanner.routing.core.State; +import org.opentripplanner.routing.core.VehicleRentalState; import org.opentripplanner.routing.edgetype.FreeEdge; import org.opentripplanner.routing.graph.Edge; import org.opentripplanner.routing.graph.Vertex; @@ -19,14 +20,17 @@ public class EuclideanRemainingWeightHeuristic implements RemainingWeightHeurist private double lat; private double lon; private double maxStreetSpeed; + private double walkingSpeed; + private boolean arriveBy; // TODO This currently only uses the first toVertex. If there are multiple toVertices, it will // not work correctly. @Override - public void initialize(RoutingRequest options, long abortTime) { - RoutingRequest req = options; + public void initialize(RoutingRequest req, long abortTime) { Vertex target = req.rctx.toVertices.iterator().next(); maxStreetSpeed = req.getStreetSpeedUpperBound(); + walkingSpeed = req.walkSpeed; + arriveBy = req.arriveBy; if (target.getDegreeIn() == 1) { Edge edge = Iterables.getOnlyElement(target.getIncoming()); @@ -46,8 +50,13 @@ public void initialize(RoutingRequest options, long abortTime) { public double estimateRemainingWeight (State s) { Vertex sv = s.getVertex(); double euclideanDistance = SphericalDistanceLibrary.fastDistance(sv.getLat(), sv.getLon(), lat, lon); - // all travel is on-street, no transit involved - return euclideanDistance / maxStreetSpeed; + // After parking or finishing the rental of a vehicle, you can't ever move faster than walking speed. + final boolean useWalkSpeed = !arriveBy && ( + s.isVehicleParked() || s.getVehicleRentalState() == VehicleRentalState.HAVE_RENTED + ); + + final double streetSpeed = useWalkSpeed ? walkingSpeed : maxStreetSpeed; + return euclideanDistance / streetSpeed; } @Override diff --git a/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/VehicleToStopSkipEdgeStrategy.java b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/VehicleToStopSkipEdgeStrategy.java new file mode 100644 index 00000000000..410750cf89e --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/astar/strategies/VehicleToStopSkipEdgeStrategy.java @@ -0,0 +1,92 @@ +package org.opentripplanner.routing.algorithm.astar.strategies; + +import java.util.Set; +import java.util.function.Function; +import org.opentripplanner.model.Route; +import org.opentripplanner.model.Stop; +import org.opentripplanner.model.TransitMode; +import org.opentripplanner.routing.api.request.RoutingRequest; +import org.opentripplanner.routing.api.request.StreetMode; +import org.opentripplanner.routing.core.State; +import org.opentripplanner.routing.graph.Edge; +import org.opentripplanner.routing.graph.Vertex; +import org.opentripplanner.routing.spt.ShortestPathTree; +import org.opentripplanner.routing.vertextype.TransitStopVertex; + +/** + * This strategy terminates when enough "important" stops are found. + *

+ * The definition of important is a stop where many routes of mode RAIL, SUBWAY or FERRY depart. + *

+ * This means that the search radius scales with density of "important" stops: + *

+ *

  • in a city the radius is quite small + *
  • in more rural regions the radius is bigger and stops further away are considered + *

    + * The strategy is useful when you want to limit the number of accesses of Park+Ride, Bike+Ride and + * Bike+Transit: it improves both performance the quality of results. + *

    + * {@see https://github.com/opentripplanner/OpenTripPlanner/pull/3906} + */ +public class VehicleToStopSkipEdgeStrategy implements SkipEdgeStrategy { + + private final Function> getRoutesForStop; + + private double sumOfScores; + private final int maxScore; + + public final static Set applicableModes = + Set.of( + StreetMode.BIKE_TO_PARK, + StreetMode.BIKE_RENTAL, + StreetMode.CAR_TO_PARK, + StreetMode.CAR_PICKUP, + StreetMode.CAR_RENTAL + ); + + + public VehicleToStopSkipEdgeStrategy(Function> getRoutesForStop) { + this.maxScore = 300; + this.getRoutesForStop = getRoutesForStop; + } + + @Override + public boolean shouldSkipEdge( + Set origins, + Set targets, + State current, + Edge edge, + ShortestPathTree spt, + RoutingRequest traverseOptions + ) { + if (current.getNonTransitMode().isWalking()) { + if (current.getVertex() instanceof TransitStopVertex) { + var stopVertex = (TransitStopVertex) current.getVertex(); + var stop = stopVertex.getStop(); + var score = getRoutesForStop.apply(stop) + .stream() + .map(Route::getMode) + .mapToInt(VehicleToStopSkipEdgeStrategy::score) + .sum(); + + sumOfScores = sumOfScores + score; + } + return false; + } else { + return sumOfScores >= maxScore; + } + } + + private static int score(TransitMode mode) { + switch (mode) { + case RAIL: + case FERRY: + case SUBWAY: + return 20; + case BUS: + return 1; + default: + return 2; + } + } +} diff --git a/src/main/java/org/opentripplanner/routing/api/request/RoutingRequest.java b/src/main/java/org/opentripplanner/routing/api/request/RoutingRequest.java index 3171212e41d..f4e986f84b0 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/RoutingRequest.java +++ b/src/main/java/org/opentripplanner/routing/api/request/RoutingRequest.java @@ -345,7 +345,7 @@ public class RoutingRequest implements AutoCloseable, Cloneable, Serializable { public double bikeReluctance = 2.0; - public double carReluctance = 2.0; + public double carReluctance = 10.0; /** diff --git a/src/main/java/org/opentripplanner/routing/core/intersection_model/SimpleIntersectionTraversalCostModel.java b/src/main/java/org/opentripplanner/routing/core/intersection_model/SimpleIntersectionTraversalCostModel.java index 27aef9ab09b..42b29bd690c 100644 --- a/src/main/java/org/opentripplanner/routing/core/intersection_model/SimpleIntersectionTraversalCostModel.java +++ b/src/main/java/org/opentripplanner/routing/core/intersection_model/SimpleIntersectionTraversalCostModel.java @@ -37,11 +37,7 @@ public double computeTraversalCost( return computeDrivingTraversalCost(v, from, to, request); } else if (mode.isCycling()) { - var c = computeCyclingTraversalCost(v, from, to, fromSpeed, toSpeed, request); - if (LOG.isTraceEnabled()) { - LOG.trace("Turning from {} to {} has a cost of {}", from, to, c); - } - return c; + return computeCyclingTraversalCost(v, from, to, fromSpeed, toSpeed, request); } else { return computeNonDrivingTraversalCost(v, from, to, fromSpeed, toSpeed); diff --git a/src/main/java/org/opentripplanner/routing/edgetype/TemporaryPartialStreetEdge.java b/src/main/java/org/opentripplanner/routing/edgetype/TemporaryPartialStreetEdge.java index 3c84dec16e8..0cdd91099dc 100644 --- a/src/main/java/org/opentripplanner/routing/edgetype/TemporaryPartialStreetEdge.java +++ b/src/main/java/org/opentripplanner/routing/edgetype/TemporaryPartialStreetEdge.java @@ -1,6 +1,7 @@ package org.opentripplanner.routing.edgetype; import java.util.Collection; +import java.util.List; import javax.annotation.Nonnull; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.LineString; @@ -10,11 +11,14 @@ import org.opentripplanner.routing.vertextype.StreetVertex; import org.opentripplanner.routing.vertextype.TemporaryVertex; import org.opentripplanner.util.I18NString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; final public class TemporaryPartialStreetEdge extends StreetWithElevationEdge implements TemporaryEdge { private static final long serialVersionUID = 1L; + private static final Logger LOG = LoggerFactory.getLogger(TemporaryPartialStreetEdge.class); /** * The edge on which this lies. @@ -86,7 +90,12 @@ public int getOutAngle() { @Nonnull @Override public Collection getTurnRestrictions() { - return parentEdge.getTurnRestrictions(); + if(parentEdge == null) { + LOG.error("{} doesn't have a parent edge!", this); + return List.of(); + } else { + return parentEdge.getTurnRestrictions(); + } } /** diff --git a/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java b/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java index 4693526a27f..fbf5780dda1 100644 --- a/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java +++ b/src/main/java/org/opentripplanner/routing/graph/GraphIndex.java @@ -7,6 +7,14 @@ import com.google.common.collect.Sets; import gnu.trove.set.TIntSet; import gnu.trove.set.hash.TIntHashSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import org.locationtech.jts.geom.Envelope; import org.opentripplanner.common.geometry.CompactElevationProfile; import org.opentripplanner.common.geometry.HashGridSpatialIndex; @@ -30,12 +38,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - public class GraphIndex { private static final Logger LOG = LoggerFactory.getLogger(GraphIndex.class); @@ -187,6 +189,12 @@ public Collection getPatternsForStop(StopLocation stop) { return patternsForStopId.get(stop); } + public Collection getTripsForStop(StopLocation stop) { + return getPatternsForStop(stop).stream() + .flatMap(TripPattern::scheduledTripsAsStream) + .collect(Collectors.toList()); + } + /** * Returns all the patterns for a specific stop. If timetableSnapshot is included, new patterns * added by realtime updates are added to the collection. A set is used here because trip diff --git a/src/main/java/org/opentripplanner/routing/spt/ShortestPathTree.java b/src/main/java/org/opentripplanner/routing/spt/ShortestPathTree.java index 6d18ce33cb7..93e5c614710 100644 --- a/src/main/java/org/opentripplanner/routing/spt/ShortestPathTree.java +++ b/src/main/java/org/opentripplanner/routing/spt/ShortestPathTree.java @@ -40,7 +40,7 @@ public ShortestPathTree (RoutingRequest options, DominanceFunction dominanceFunc } /** @return a list of GraphPaths, sometimes empty but never null. */ - public List getPaths(Vertex dest, boolean optimize) { + public List getPaths(Vertex dest) { List stateList = getStates(dest); if (stateList == null) { return Collections.emptyList(); @@ -58,7 +58,7 @@ public List getPaths(Vertex dest, boolean optimize) { public List getPaths() { List graphPaths = new ArrayList<>(); for (Vertex vertex : options.getRoutingContext().toVertices) { - graphPaths.addAll(getPaths(vertex, true)); + graphPaths.addAll(getPaths(vertex)); } return graphPaths; } diff --git a/src/main/java/org/opentripplanner/util/OTPFeature.java b/src/main/java/org/opentripplanner/util/OTPFeature.java index 7cbf42629a5..9da1e0b886d 100644 --- a/src/main/java/org/opentripplanner/util/OTPFeature.java +++ b/src/main/java/org/opentripplanner/util/OTPFeature.java @@ -36,7 +36,8 @@ public enum OTPFeature { SandboxAPITransmodelApi(false), SandboxExampleAPIGraphStatistics(false), SandboxAPIParkAndRideApi(false), - TransferAnalyzer(false); + TransferAnalyzer(false), + VehicleToStopHeuristics(false); private static final Logger LOG = LoggerFactory.getLogger(OTPFeature.class); diff --git a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java index e4ae2c2b56c..754eaff37e5 100644 --- a/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java +++ b/src/main/java/org/opentripplanner/visualizer/GraphVisualizer.java @@ -1473,7 +1473,7 @@ public int compare(Vertex arg0, Vertex arg1) { } } if(target!=null && spt!=null){ - List paths = spt.getPaths(target,true); + List paths = spt.getPaths(target); showPathsInPanel( paths ); } } diff --git a/src/test/java/org/opentripplanner/routing/algorithm/CarParkAndRideTest.java b/src/test/java/org/opentripplanner/routing/algorithm/CarParkAndRideTest.java index 50b9724dff7..26231eb56bb 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/CarParkAndRideTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/CarParkAndRideTest.java @@ -106,11 +106,11 @@ public void exitOnWalkableEntranceCarParkingTest() { assertPath( A, B, StreetMode.CAR_TO_PARK, "null - null (0.00, 0)", - "CAR - AB street (15.54, 8)", - "null - CarPark #1 Entrance B (16.54, 8)", - "null (parked) - CarPark #1 Entrance A (256.54, 188)", - "null (parked) - CarPark #1 Entrance A (257.54, 188)", - "WALK (parked) - AB street (388.36, 254)" + "CAR - AB street (77.68, 8)", + "null - CarPark #1 Entrance B (78.68, 8)", + "null (parked) - CarPark #1 Entrance A (318.68, 188)", + "null (parked) - CarPark #1 Entrance A (319.68, 188)", + "WALK (parked) - AB street (450.51, 254)" ); } diff --git a/src/test/java/org/opentripplanner/routing/street/CarRoutingTest.java b/src/test/java/org/opentripplanner/routing/street/CarRoutingTest.java index 429c4407088..c04bf708cd5 100644 --- a/src/test/java/org/opentripplanner/routing/street/CarRoutingTest.java +++ b/src/test/java/org/opentripplanner/routing/street/CarRoutingTest.java @@ -53,7 +53,7 @@ public void shouldAllowLoopCausedByTurnRestrictions() { ConstantsForTests.HERRENBERG_HINDENBURG_STR_UNDER_CONSTRUCTION_OSM ); - var gueltsteinerStr = new GenericLocation(48.59240, 8.87024); + var gueltsteinerStr = new GenericLocation(48.59364, 8.87078); var aufDemGraben = new GenericLocation(48.59487, 8.87133); var polyline = @@ -61,7 +61,7 @@ public void shouldAllowLoopCausedByTurnRestrictions() { assertThatPolylinesAreEqual( polyline, - "ouqgH}mcu@gAE]U}BaA]Q}@]uAs@[SAm@Ee@AUEi@XEQkBQ?Bz@Dt@Dh@@TGBC@KBSHGx@" + "g}qgHgqcu@IE}@]uAs@[SAm@Ee@AUEi@XEQkBQ?Bz@Dt@Dh@@TGBC@KBSHGx@" ); }