package org.opentripplanner.routing.core;
import org.opentripplanner.routing.edgetype.StreetEdge;
import org.opentripplanner.routing.edgetype.StreetTraversalPermission;
import lombok.Data;
/**
* Preferences for how to traverse the graph.
*
* @author avi
*/
@Data
public class TraversalRequirements {
/**
* Modes allowed in graph traversal. Defaults to allowing all.
*/
private TraverseModeSet modes = TraverseModeSet.allModes();
/**
* The maximum distance (meters) the user is willing to walk. Defaults to 1/2 mile.
*/
private double maxWalkDistance = 800;
/**
* If true, trip must be wheelchair accessible.
*/
private boolean wheelchairAccessible = false;
/**
* The maximum slope of streets for wheelchair trips.
*
* ADA max wheelchair ramp slope is a good default.
*/
private double maxWheelchairSlope = 0.0833333333333;
/**
* Specific requirements for walking a bicycle.
*/
private TraversalRequirements bikeWalkingRequirements;
/**
* Default constructor.
*
* By default, accepts all modes of travel and does not require wheelchair access.
*/
public TraversalRequirements() {
}
/**
* Construct from RoutingRequest.
*
* @param options
*/
public TraversalRequirements(RoutingRequest options) {
this();
if (options == null) {
return;
}
// Initialize self.
initFromRoutingRequest(this, options);
// Initialize walking requirements if any given.
RoutingRequest bikeWalkOptions = options.getBikeWalkingOptions();
if (bikeWalkOptions != null) {
bikeWalkingRequirements = new TraversalRequirements();
initFromRoutingRequest(bikeWalkingRequirements, bikeWalkOptions);
}
}
/**
* Initialize TraversalRequirements from a RoutingRequest.
*
* @param req
* @param options
*/
private static void initFromRoutingRequest(TraversalRequirements req, RoutingRequest options) {
req.modes = options.getModes().clone();
req.wheelchairAccessible = options.wheelchairAccessible;
req.maxWheelchairSlope = options.maxSlope;
req.maxWalkDistance = options.maxWalkDistance;
}
/**
* Returns true if bike walking requirements are defined.
*
* @return
*/
public boolean hasBikeWalkingRequirements() {
return bikeWalkingRequirements != null;
}
/** Returns true if this StreetEdge can be traversed. */
private boolean canBeTraversedInternal(StreetEdge e) {
if (wheelchairAccessible) {
if (!e.isWheelchairAccessible()) {
return false;
}
if (e.getElevationProfileSegment().getMaxSlope() > maxWheelchairSlope) {
return false;
}
}
return e.getPermission().allows(modes);
}
/**
* Returns true if this StreetEdge can be traversed.
* Also checks if we can walk our bike on this StreetEdge.
*/
public boolean canBeTraversed(StreetEdge e) {
if (canBeTraversedInternal(e)) {
return true;
} else if (hasBikeWalkingRequirements()
&& bikeWalkingRequirements.canBeTraversedInternal(e)) {
return true;
}
return false;
}
}