org.opentripplanner.model.plan.WalkStep Maven / Gradle / Ivy
package org.opentripplanner.model.plan;
import com.google.common.collect.Lists;
import org.opentripplanner.common.model.P2;
import org.opentripplanner.model.BikeRentalStationInfo;
import org.opentripplanner.model.StreetNote;
import org.opentripplanner.model.WgsCoordinate;
import org.opentripplanner.routing.graph.Edge;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Represents one instruction in walking directions. Three examples from New York City:
*
* Turn onto Broadway from W 57th St (coming from 7th Ave):
* distance = 100 (say)
* walkDirection = RIGHT
* streetName = Broadway
* everything else null/false
*
*
* Now, turn from Broadway onto Central Park S via Columbus Circle
* distance = 200 (say)
* walkDirection = CIRCLE_COUNTERCLOCKWISE
* streetName = Central Park S
* exit = 1 (first exit)
* immediately everything else false
*
*
* Instead, go through the circle to continue on Broadway
* distance = 100 (say)
* walkDirection = CIRCLE_COUNTERCLOCKWISE
* streetName = Broadway
* exit = 3
* stayOn = true
* everything else false
*
*/
public class WalkStep {
/**
* The distance in meters that this step takes.
*/
public double distance = 0;
/**
* The relative direction of this step.
*/
public RelativeDirection relativeDirection;
/**
* The name of the street.
*/
public String streetName;
/**
* The absolute direction of this step.
*/
public AbsoluteDirection absoluteDirection;
/**
* When exiting a highway or traffic circle, the exit name/number.
*/
public String exit;
/**
* Indicates whether or not a street changes direction at an intersection.
*/
public Boolean stayOn = false;
/**
* This step is on an open area, such as a plaza or train platform, and thus the directions should say something like "cross"
*/
public Boolean area = false;
/**
* The name of this street was generated by the system, so we should only display it once, and generally just display right/left directions
*/
public Boolean bogusName = false;
/**
* The coordinate of start of the step
*/
public WgsCoordinate startLocation;
/**
* The elevation profile as a comma-separated list of x,y values. x is the distance from the start of the step, y is the elevation at this
* distance.
*/
public List> elevation;
public final Set streetNotes = new HashSet<>();
public double angle;
/**
* The street edges that make up this walkStep.
* Used only in generating the streetEdges array in StreetSegment; not serialized.
*/
public List edges = Lists.newArrayList();
/**
* The bike rental on/off station info.
* Used only in generating the streetEdges array in StreetSegment; not serialized.
*/
public BikeRentalStationInfo bikeRentalOnStation;
public BikeRentalStationInfo bikeRentalOffStation;
public void setDirections(double lastAngle, double thisAngle, boolean roundabout) {
relativeDirection = getRelativeDirection(lastAngle, thisAngle, roundabout);
setAbsoluteDirection(thisAngle);
}
public void setAbsoluteDirection(double thisAngle) {
int octant = (int) (8 + Math.round(thisAngle * 8 / (Math.PI * 2))) % 8;
absoluteDirection = AbsoluteDirection.values()[octant];
}
public List> getElevation() {
return elevation;
}
public void addStreetNotes(Collection streetNotes) {
if(streetNotes == null) { return; }
this.streetNotes.addAll(streetNotes);
}
public static RelativeDirection getRelativeDirection(double lastAngle, double thisAngle,
boolean roundabout) {
double angleDiff = thisAngle - lastAngle;
if (angleDiff < 0) {
angleDiff += Math.PI * 2;
}
double ccwAngleDiff = Math.PI * 2 - angleDiff;
if (roundabout) {
// roundabout: the direction we turn onto it implies the circling direction
if (angleDiff > ccwAngleDiff) {
return RelativeDirection.CIRCLE_CLOCKWISE;
} else {
return RelativeDirection.CIRCLE_COUNTERCLOCKWISE;
}
}
// less than 0.3 rad counts as straight, to simplify walking instructions
if (angleDiff < 0.3 || ccwAngleDiff < 0.3) {
return RelativeDirection.CONTINUE;
} else if (angleDiff < 0.7) {
return RelativeDirection.SLIGHTLY_RIGHT;
} else if (ccwAngleDiff < 0.7) {
return RelativeDirection.SLIGHTLY_LEFT;
} else if (angleDiff < 2) {
return RelativeDirection.RIGHT;
} else if (ccwAngleDiff < 2) {
return RelativeDirection.LEFT;
} else if (angleDiff < Math.PI) {
return RelativeDirection.HARD_RIGHT;
} else {
return RelativeDirection.HARD_LEFT;
}
}
public String streetNameNoParens() {
int idx = streetName.indexOf('(');
if (idx <= 0) {
return streetName;
}
return streetName.substring(0, idx - 1);
}
@Override
public String toString() {
String direction = absoluteDirection.toString();
if (relativeDirection != null) {
direction = relativeDirection.toString();
}
return "WalkStep(" + direction + " on " + streetName + " for " + distance + ")";
}
}