Hi,
As part of our routing we support Historical speeds based on a time band, for example.
34.28@(Mo-Fr04:00-07:00);28.49@(Mo-Fr07:00-09:00);30.74@(Mo-Fr09:00-12:00);31.7@(Mo-Fr12:00-14:00);30.58@(Mo-Fr14:00-16:00);27.84@(Mo-Fr16:00-19:00);23.82@(Mo-Fr19:00-22:00);35.24@(Mo-Fr22:00-04:00);26.23@(Sa-Su04:00-07:00);25.75@(Sa-Su07:00-10:00);
As part of calculating the weight per edge i am hardcoding a time band range for testing “16:00-19:00” these weights come from OS road data which provides the weight of each edge based on the time of the day.
If the edge has a time band weight “weight @” then we will use this as the return, if no weight is present for the edge then use the default logic.
When i pick a time band such as rush hour 16:00-19:00 there is no difference in the route select than picking a route for 04:00-07:00 which obviously in there would be in places such as London
@Override
public double calcEdgeWeight(EdgeIteratorState edgeState, boolean reverse) {
double priority = edgeToPriorityMapping.get(edgeState, reverse);
if (priority == 0) return Double.POSITIVE_INFINITY;
final double distance = edgeState.getDistance();
double speed = 0;
Map<String, KVStorage.KValue> obj = edgeState.getKeyValues();
String fullTimebands = null;
if (reverse) {
KVStorage.KValue value = obj.get("avgspeed_backward_conditional");
fullTimebands = (value != null) ? value.toString() : null;
} else {
KVStorage.KValue value = obj.get("avgspeed_forward_conditional");
fullTimebands = (value != null) ? value.toString() : null;
}
if (fullTimebands != null) {
Pattern timebandRegex = Pattern.compile("([\\d.]+)@\\(Mo-Fr16:00-19:00\\)");
Matcher matcher = timebandRegex.matcher(fullTimebands);
if (matcher.find()) {
String speedStr = matcher.group(1);
if (speedStr != null && !speedStr.isEmpty()) {
speed = Double.parseDouble(speedStr);
}
}
}
if (speed <= 0) {
speed = edgeToSpeedMapping.get(edgeState, reverse);
if (speed <= 0) return Double.POSITIVE_INFINITY;
}
double seconds = distance / speed * SPEED_CONV;
if (Double.isInfinite(seconds)) return Double.POSITIVE_INFINITY;
if (edgeState.get(EdgeIteratorState.UNFAVORED_EDGE)) {
seconds += headingPenaltySeconds;
}
double distanceCosts = distance * distanceInfluence;
if (Double.isInfinite(distanceCosts)) return Double.POSITIVE_INFINITY;
return seconds / priority + distanceCosts;
}