Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void filter() {
private static Collection<ClosestTrip> closestTrips(Matcher<Trip> matcher) {
return ClosestTrip.of(
ADAPTER,
List.of(new NearbyStop(STOP, 100, List.of(), null)),
List.of(new NearbyStop(STOP, 100, List.of(), List.of())),
matcher,
List.of(FSD),
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.Set;
import org.opentripplanner.astar.model.GraphPath;
import org.opentripplanner.astar.strategy.DurationSkipEdgeStrategy;
import org.opentripplanner.astar.strategy.PathComparator;
import org.opentripplanner.core.model.i18n.NonLocalizedString;
import org.opentripplanner.model.GenericLocation;
import org.opentripplanner.routing.api.request.RouteRequest;
Expand Down Expand Up @@ -195,13 +194,6 @@ private GraphPath<State, Edge, Vertex> carpoolRouting(
.withFrom(fromVertices)
.withTo(toVertices);

List<GraphPath<State, Edge, Vertex>> paths = streetSearch.getPathsToTarget();
paths.sort(new PathComparator(request.arriveBy()));

if (paths.isEmpty()) {
return null;
}

return paths.getFirst();
return streetSearch.getPathToTarget().orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ Stream<FlexAccessEgress> createFlexAccessEgressStream(FlexAccessEgressCallbackAd
// transferStop is Location Area/Line
else {
double maxDistanceMeters =
maxTransferDuration.getSeconds() * accessEgress.state.getRequest().walk().speed();
maxTransferDuration.getSeconds() *
accessEgress.lastStates.getFirst().getRequest().walk().speed();

return getTransfersFromTransferStop(callback)
.stream()
Expand Down Expand Up @@ -192,7 +193,10 @@ private FlexAccessEgress createFlexAccessEgress(
// this code is a little repetitive but needed as a performance improvement. previously
// the flex path was checked before this method was called. this meant that every path
// was traversed twice, leading to a noticeable slowdown.
final var afterFlexState = flexEdge.traverse(accessEgress.state);

// TODO flex routing doesn't support via locations yet
var lastState = accessEgress.lastStates.getFirst();
final var afterFlexState = flexEdge.traverse(lastState);
if (State.isEmpty(afterFlexState)) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ protected Vertex getFlexVertex(Edge edge) {
}

protected FlexPathDurations calculateFlexPathDurations(FlexTripEdge flexEdge, State state) {
int preFlexTime = (int) accessEgress.state.getElapsedTimeSeconds();
int preFlexTime = (int) accessEgress.duration().getSeconds();
int edgeTimeInSeconds = flexEdge.getTimeInSeconds();
int postFlexTime = (int) state.getElapsedTimeSeconds() - preFlexTime - edgeTimeInSeconds;
return new FlexPathDurations(
Expand All @@ -70,8 +70,10 @@ protected FlexPathDurations calculateFlexPathDurations(FlexTripEdge flexEdge, St
}

protected FlexTripEdge getFlexEdge(Vertex flexToVertex, StopLocation transferStop) {
// TODO flex doesn't support via locations yet
var lastVertex = accessEgress.lastStates.getLast().getVertex();
var flexPath = calculator.calculateFlexPath(
accessEgress.state.getVertex(),
lastVertex,
flexToVertex,
boardStopPosition,
alightStopPosition
Expand All @@ -82,7 +84,7 @@ protected FlexTripEdge getFlexEdge(Vertex flexToVertex, StopLocation transferSto
}

return new FlexTripEdge(
accessEgress.state.getVertex(),
lastVertex,
flexToVertex,
accessEgress.stop,
transferStop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ private Optional<DirectFlexPath> createDirectGraphPath(
int accessAlightStopPosition = accessTemplate.alightStopPosition;
int requestedBookingTime = accessTemplate.requestedBookingTime;

var flexToVertex = egress.state.getVertex();
// TODO flex doesn't support via locations yet
var flexToVertex = egress.lastStates.getLast().getVertex();

if (!isRouteable(accessTemplate, flexToVertex)) {
return Optional.empty();
Expand All @@ -117,7 +118,9 @@ private Optional<DirectFlexPath> createDirectGraphPath(
return Optional.empty();
}

final State[] afterFlexState = flexEdge.traverse(accessNearbyStop.state);
// TODO flex doesn't support via locations yet
var lastState = accessNearbyStop.lastStates.getLast();
final State[] afterFlexState = flexEdge.traverse(lastState);

var finalStateOpt = EdgeTraverser.traverseEdges(afterFlexState[0], egress.edges);

Expand Down Expand Up @@ -183,12 +186,14 @@ private Optional<DirectFlexPath> createDirectGraphPath(
}

protected boolean isRouteable(FlexAccessTemplate accessTemplate, Vertex flexVertex) {
if (accessTemplate.accessEgress.state.getVertex() == flexVertex) {
// TODO flex doesn't support via locations yet
var lastVertex = accessTemplate.accessEgress.lastStates.getLast().getVertex();
if (lastVertex == flexVertex) {
return false;
} else {
return (
accessTemplate.calculator.calculateFlexPath(
accessTemplate.accessEgress.state.getVertex(),
lastVertex,
flexVertex,
accessTemplate.boardStopPosition,
accessTemplate.alightStopPosition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ protected Vertex getFlexVertex(Edge edge) {
}

protected FlexPathDurations calculateFlexPathDurations(FlexTripEdge flexEdge, State state) {
int postFlexTime = (int) accessEgress.state.getElapsedTimeSeconds();
int postFlexTime = (int) accessEgress.duration().getSeconds();
int edgeTimeInSeconds = flexEdge.getTimeInSeconds();
int preFlexTime = (int) state.getElapsedTimeSeconds() - postFlexTime - edgeTimeInSeconds;
return new FlexPathDurations(
Expand All @@ -71,9 +71,11 @@ protected FlexPathDurations calculateFlexPathDurations(FlexTripEdge flexEdge, St
}

protected FlexTripEdge getFlexEdge(Vertex flexFromVertex, StopLocation transferStop) {
// TODO flex doesn't support via locations yet
var lastVertex = accessEgress.lastStates.getLast().getVertex();
var flexPath = calculator.calculateFlexPath(
flexFromVertex,
accessEgress.state.getVertex(),
lastVertex,
boardStopPosition,
alightStopPosition
);
Expand All @@ -84,7 +86,7 @@ protected FlexTripEdge getFlexEdge(Vertex flexFromVertex, StopLocation transferS

return new FlexTripEdge(
flexFromVertex,
accessEgress.state.getVertex(),
lastVertex,
transferStop,
accessEgress.stop,
trip,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public final class RideHailingAccessAdapter extends DefaultAccessEgress {
private final Duration arrival;

public RideHailingAccessAdapter(RoutingAccessEgress access, Duration arrival) {
super(access.stop(), access.getLastState());
super(access.stop(), access.getLastStates());
this.arrival = arrival;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.opentripplanner.routing.algorithm.raptoradapter.transit.RoutingAccessEgress;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.street.search.state.State;
import org.opentripplanner.transit.model.framework.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -45,7 +46,7 @@ public static List<RoutingAccessEgress> shiftAccesses(
.map(ae -> {
// only time-shift access legs on a car
// (there could be walk-only accesses if you're close to the stop)
if (isAccess && ae.getLastState().containsModeCar()) {
if (isAccess && ae.getLastStates().stream().allMatch(State::containsModeCar)) {
var duration = fetchArrivalDelay(services, request, now);
if (duration.isSuccess()) {
return new RideHailingAccessAdapter(ae, duration.successValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ public DataFetcher<Object> node() {
var stop = transitService.getRegularStop(FeedScopedId.parse(parts[1]));

// TODO: Add geometry
return new NearbyStop(stop, Integer.parseInt(parts[0]), null, null);
return new NearbyStop(stop, Integer.parseInt(parts[0]), List.of(), List.of());
}
case "TicketType":
// TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,12 @@ public DataFetcher<Iterable<NearbyStop>> transfers() {
.filter(transfer -> maxDistance == null || transfer.getDistanceMeters() < maxDistance)
.filter(transfer -> transfer.to instanceof RegularStop)
.map(transfer ->
new NearbyStop(transfer.to, transfer.getDistanceMeters(), transfer.getEdges(), null)
new NearbyStop(
transfer.to,
transfer.getDistanceMeters(),
transfer.getEdges(),
List.of()
)
)
.collect(Collectors.toList());
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.opentripplanner.routing.algorithm.raptoradapter.router.FilterTransitWhenDirectModeIsEmpty;
import org.opentripplanner.routing.algorithm.raptoradapter.router.TransitRouter;
import org.opentripplanner.routing.algorithm.raptoradapter.router.street.DirectFlexRouter;
import org.opentripplanner.routing.algorithm.raptoradapter.router.street.DirectStreetRouter;
import org.opentripplanner.routing.algorithm.raptoradapter.router.street.DirectStreetRouterFactory;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.routing.api.request.request.StreetRequest;
Expand Down Expand Up @@ -226,14 +226,6 @@ private Duration searchWindowUsed() {
}

private RoutingResult routeDirectStreet() {
// TODO: Add support for via search to the direct-street search and remove this.
// The direct search is used to prune away silly transit results and it
// would be nice to also support via as a feature in the direct-street
// search.
if (request.isViaSearch()) {
return RoutingResult.empty();
}

// If no direct mode is set, then we set one.
// See {@link FilterTransitWhenDirectModeIsEmpty}
var emptyDirectModeHandler = new FilterTransitWhenDirectModeIsEmpty(
Expand All @@ -253,8 +245,12 @@ private RoutingResult routeDirectStreet() {

debugTimingAggregator.startedDirectStreetRouter();
try {
var directRouter = DirectStreetRouterFactory.create(request);
return RoutingResult.ok(
DirectStreetRouter.route(serverContext, directBuilder.buildRequest(), linkingContext()),
directRouter
.route(serverContext, directBuilder.buildRequest(), linkingContext())
.stream()
.toList(),
emptyDirectModeHandler.removeWalkAllTheWayResults()
);
} catch (RoutingValidationException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.LineString;
Expand Down Expand Up @@ -101,62 +102,93 @@ public static boolean isFloatingRentalDropoff(State state) {
}

/**
* Generates a TripPlan from a set of paths
* Generates a TripPlan from a set of paths. Each path generates a leg in the itinerary.
*/
public List<Itinerary> mapItineraries(

public Optional<Itinerary> mapToItinerary(
List<GraphPath<State, Edge, Vertex>> paths,
RouteRequest request
) {
List<Itinerary> itineraries = new LinkedList<>();
for (GraphPath<State, Edge, Vertex> path : paths) {
Itinerary itinerary = generateItinerary(path, request);
if (itinerary.legs().isEmpty()) {
continue;
}
itineraries.add(itinerary);
Itinerary itinerary = generateItinerary(paths, request);
if (itinerary.legs().isEmpty()) {
return Optional.empty();
}

return itineraries;
return Optional.of(itinerary);
}

/**
* Generate an itinerary from a {@link GraphPath}. This method first slices the list of states at
* the leg boundaries. These smaller state arrays are then used to generate legs.
* Generates a TripPlan from a path.
*/
public Optional<Itinerary> mapToItinerary(
GraphPath<State, Edge, Vertex> path,
RouteRequest request
) {
return mapToItinerary(List.of(path), request);
}

/**
* Generate an itinerary from a list {@link GraphPath}s. Each path generates one more or more
* legs. This method first slices the list of states at the leg boundaries. These smaller state
* arrays are then used to generate legs.
*
* @param path The graph path to base the itinerary on
* @param paths The graph paths to base the itinerary on
* @return The generated itinerary
*/
public Itinerary generateItinerary(GraphPath<State, Edge, Vertex> path, RouteRequest request) {
public Itinerary generateItinerary(
List<GraphPath<State, Edge, Vertex>> paths,
RouteRequest request
) {
List<Leg> legs = new ArrayList<>();
WalkStep previousStep = null;
for (List<State> legStates : sliceStates(path.states)) {
if (OTPFeature.FlexRouting.isOn() && legStates.get(1).backEdge instanceof FlexTripEdge) {
legs.add(generateFlexLeg(legStates));
previousStep = null;
continue;
}
StreetLeg leg = generateLeg(legStates, previousStep, request);
legs.add(leg);

List<WalkStep> walkSteps = leg.listWalkSteps();
if (walkSteps.size() > 0) {
previousStep = walkSteps.get(walkSteps.size() - 1);
} else {
previousStep = null;
for (GraphPath<State, Edge, Vertex> path : paths) {
WalkStep previousStep = null;
for (List<State> legStates : sliceStates(path.states)) {
if (OTPFeature.FlexRouting.isOn() && legStates.get(1).backEdge instanceof FlexTripEdge) {
legs.add(generateFlexLeg(legStates));
previousStep = null;
continue;
}
StreetLeg leg = generateLeg(legStates, previousStep, request);
legs.add(leg);

List<WalkStep> walkSteps = leg.listWalkSteps();
if (walkSteps.size() > 0) {
previousStep = walkSteps.get(walkSteps.size() - 1);
} else {
previousStep = null;
}
}
}

State lastState = path.states.getLast();
var cost = Cost.costOfSeconds(lastState.weight);
var cost = Cost.costOfSeconds(
paths.stream().map(GraphPath::getWeight).reduce(0.0, Double::sum)
);
var builder = Itinerary.ofDirect(legs).withGeneralizedCost(cost);

builder.withArrivedAtDestinationWithRentedVehicle(lastState.isRentingVehicleFromStation());
builder.withArrivedAtDestinationWithRentedVehicle(
paths.getLast().states.getLast().isRentingVehicleFromStation()
);

calculateElevations(builder, path.edges);
var allEdges = paths
.stream()
.flatMap(p -> p.edges.stream())
.toList();
calculateElevations(builder, allEdges);

return builder.build();
}

/**
* Generate an itinerary from a {@link GraphPath}. This method first slices the list of states at
* the leg boundaries. These smaller state arrays are then used to generate legs.
*
* @param path The graph path to base the itinerary on
* @return The generated itinerary
*/
public Itinerary generateItinerary(GraphPath<State, Edge, Vertex> path, RouteRequest request) {
return generateItinerary(List.of(path), request);
}

/**
* Slice a {@link State} list at the leg boundaries.
*
Expand Down
Loading
Loading