
org.opentripplanner.raptor.api.path.PathLeg Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
The newest version!
package org.opentripplanner.raptor.api.path;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
import org.opentripplanner.framework.time.DurationUtils;
import org.opentripplanner.framework.time.TimeUtils;
import org.opentripplanner.raptor.api.model.RaptorTripSchedule;
/**
* A leg in a Raptor path. The legs are linked together from the first leg {@link AccessPathLeg}, to
* the last leg {@link EgressPathLeg}. There must be at least one {@link TransitPathLeg}. Transit
* legs can follow each* other or be connected by one {@link TransferPathLeg}. Note! Access and
* egress path legs may contain more than one "OTP leg", but inside raptor these are threaded as one
* leg; hence also just one leg returned by Raptor.
*
* This interface contain utility methods to _cast_ a leg into the concrete sub-type:
*
* if(leg.isTransitLeg()) {
* trip = leg.asTransitLeg().trip();
* }
*
*
* @param The TripSchedule type defined by the user of the raptor API.
*/
public interface PathLeg {
/**
* The time when the leg start/depart from the leg origin. For transit the time do NOT include
* boardSlack.
*/
int fromTime();
/**
* The stop place where the leg start/depart from.
*
* @throws IllegalArgumentException if leg does not start at a stop, like an access leg.
*/
default int fromStop() {
throw new IllegalStateException("Leg does not start fro a stop: " + this);
}
/**
* The time when the leg end/arrive at the leg destination. For transit the time do NOT include
* alight-slack.
*/
int toTime();
/**
* The stop where the leg end/arrive at the leg destination.
*
* @throws IllegalArgumentException if leg does not end at a stop, like an egress leg.
*/
default int toStop() {
throw new IllegalStateException("Leg does not end at a stop: " + this);
}
/**
* Number of seconds to travel this leg. This does not include slack/wait time.
*/
default int duration() {
return toTime() - fromTime();
}
/**
* The computed generalized-cost for this path leg.
*
* {@code -1} is returned if no cost exist.
*
* The unit is centi-seconds (Raptor cost unit)
*/
int c1();
/**
* The c1 for this leg plus all legs following it.
*
* {@code -1} is returned if no cost is computed by raptor.
*
* The unit is centi-seconds (Raptor cost unit)
*/
default int c1Total() {
if (c1() < 0) {
return c1();
}
return stream().mapToInt(PathLeg::c1).sum();
}
/**
* @return {@code true} if access leg, if not {@code false}.
*/
default boolean isAccessLeg() {
return false;
}
/**
* Utility method performing a cast to {@link AccessPathLeg}, use with care:
*
* if(it.isAccessLeg()} {
* AccessPathLeg<T> transit = it.asAccessLeg();
* ...
*
*/
default AccessPathLeg asAccessLeg() {
return (AccessPathLeg) this;
}
/**
* @return {@code true} if transit leg, if not {@code false}.
*/
default boolean isTransitLeg() {
return false;
}
/**
* Utility method performing a cast to {@link TransitPathLeg}, use with care:
*
* if(it.isTransitLeg()} {
* TransitPathLeg<T> transit = it.asTransitLeg();
* ...
*
*/
default TransitPathLeg asTransitLeg() {
return (TransitPathLeg) this;
}
/**
* @return {@code true} if transfer leg, if not {@code false}.
*/
default boolean isTransferLeg() {
return false;
}
/**
* Utility method performing a cast to {@link TransferPathLeg}, use with care:
*
* if(it.isTransferLeg()} {
* TransferPathLeg<T> transfer = it.asTransferLeg();
* ...
*
*/
default TransferPathLeg asTransferLeg() {
return (TransferPathLeg) this;
}
/**
* @return {@code true} if egress leg, if not {@code false}.
*/
default boolean isEgressLeg() {
return false;
}
/**
* Utility method performing a cast to {@link EgressPathLeg}, use with care:
*
* if(it.isEgressLeg()} {
* EgressPathLeg<T> egress = it.asEgressLeg();
* ...
*
*/
default EgressPathLeg asEgressLeg() {
return (EgressPathLeg) this;
}
/**
*
* - An access leg is always followed by a transit leg.
*
- A transit leg can be followed by a new transit leg, an transfer leg or an egress leg.
*
- A transfer leg can only be followed by a transit leg.
*
- An egress leg is always the last leg and this method will throw a {@link UnsupportedOperationException}.
* Use the {@link #isEgressLeg()} to check if the last leg is reached.
*
*
* @return Next leg in path.
*/
PathLeg nextLeg();
default String asString(int toStop) {
return asString() + " ~ " + toStop;
}
default String asString() {
return (
TimeUtils.timeToStrCompact(fromTime()) +
"-" +
TimeUtils.timeToStrCompact(toTime()) +
"(" +
DurationUtils.durationToStr(duration()) +
")"
);
}
/**
* Return the next transit leg in the path after this one, if no more transit exist before
* reaching the destination {@code null} is returned.
*/
@Nullable
default TransitPathLeg nextTransitLeg() {
PathLeg leg = nextLeg();
while (!leg.isEgressLeg()) {
if (leg.isTransitLeg()) {
return leg.asTransitLeg();
}
leg = leg.nextLeg();
}
return null;
}
default Stream> stream() {
return StreamSupport.stream(iterator().spliterator(), false);
}
default Iterable> iterator() {
return () ->
new Iterator<>() {
private PathLeg currentLeg = PathLeg.this;
@Override
public boolean hasNext() {
return currentLeg != null;
}
@Override
public PathLeg next() {
var temp = currentLeg;
currentLeg = currentLeg.isEgressLeg() ? null : currentLeg.nextLeg();
return temp;
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy