Merge pull request #9277 from osmandapp/directional_traffic_signals
Directional traffic signals #6774
This commit is contained in:
commit
af5fc8ffd2
7 changed files with 143 additions and 55 deletions
|
@ -1,9 +1,25 @@
|
||||||
package net.osmand.binary;
|
package net.osmand.binary;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import com.google.protobuf.CodedInputStream;
|
import com.google.protobuf.CodedInputStream;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import com.google.protobuf.WireFormat;
|
import com.google.protobuf.WireFormat;
|
||||||
|
|
||||||
|
import gnu.trove.iterator.TLongObjectIterator;
|
||||||
|
import gnu.trove.list.array.TIntArrayList;
|
||||||
|
import gnu.trove.list.array.TLongArrayList;
|
||||||
|
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||||
|
import gnu.trove.map.hash.TLongObjectHashMap;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
import net.osmand.ResultMatcher;
|
import net.osmand.ResultMatcher;
|
||||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||||
|
@ -18,23 +34,6 @@ import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
import net.osmand.util.OpeningHoursParser;
|
import net.osmand.util.OpeningHoursParser;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import gnu.trove.iterator.TLongObjectIterator;
|
|
||||||
import gnu.trove.list.array.TIntArrayList;
|
|
||||||
import gnu.trove.list.array.TLongArrayList;
|
|
||||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
|
||||||
import gnu.trove.map.hash.TLongObjectHashMap;
|
|
||||||
|
|
||||||
public class BinaryMapRouteReaderAdapter {
|
public class BinaryMapRouteReaderAdapter {
|
||||||
protected static final Log LOG = PlatformUtil.getLog(BinaryMapRouteReaderAdapter.class);
|
protected static final Log LOG = PlatformUtil.getLog(BinaryMapRouteReaderAdapter.class);
|
||||||
private static final int SHIFT_COORDINATES = 4;
|
private static final int SHIFT_COORDINATES = 4;
|
||||||
|
@ -172,7 +171,7 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
}
|
}
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int onewayDirection(){
|
public int onewayDirection(){
|
||||||
if(type == ONEWAY){
|
if(type == ONEWAY){
|
||||||
return intValue;
|
return intValue;
|
||||||
|
@ -297,6 +296,14 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
List<RouteSubregion> subregions = new ArrayList<RouteSubregion>();
|
List<RouteSubregion> subregions = new ArrayList<RouteSubregion>();
|
||||||
List<RouteSubregion> basesubregions = new ArrayList<RouteSubregion>();
|
List<RouteSubregion> basesubregions = new ArrayList<RouteSubregion>();
|
||||||
|
|
||||||
|
public int directionForward = -1;
|
||||||
|
public int directionBackward = -1;
|
||||||
|
public int directionTrafficSignalsForward = -1;
|
||||||
|
public int directionTrafficSignalsBackward = -1;
|
||||||
|
public int trafficSignals = -1;
|
||||||
|
public int stopSign = -1;
|
||||||
|
public int giveWaySign = -1;
|
||||||
|
|
||||||
int nameTypeRule = -1;
|
int nameTypeRule = -1;
|
||||||
int refTypeRule = -1;
|
int refTypeRule = -1;
|
||||||
int destinationTypeRule = -1;
|
int destinationTypeRule = -1;
|
||||||
|
@ -353,9 +360,28 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
destinationTypeRule = id;
|
destinationTypeRule = id;
|
||||||
} else if (tags.equals("destination:ref") || tags.equals("destination:ref:forward") || tags.equals("destination:ref:backward")) {
|
} else if (tags.equals("destination:ref") || tags.equals("destination:ref:forward") || tags.equals("destination:ref:backward")) {
|
||||||
destinationRefTypeRule = id;
|
destinationRefTypeRule = id;
|
||||||
|
} else if (tags.equals("highway") && val.equals("traffic_signals")){
|
||||||
|
trafficSignals = id;
|
||||||
|
} else if (tags.equals("highway") && val.equals("stop")){
|
||||||
|
stopSign = id;
|
||||||
|
} else if (tags.equals("highway") && val.equals("give_way")){
|
||||||
|
giveWaySign = id;
|
||||||
|
} else if (tags.equals("traffic_signals:direction")){
|
||||||
|
if (val.equals("forward")) {
|
||||||
|
directionTrafficSignalsForward = id;
|
||||||
|
} else if (val.equals("backward")) {
|
||||||
|
directionTrafficSignalsBackward = id;
|
||||||
|
}
|
||||||
|
} else if (tags.equals("direction")) {
|
||||||
|
if (val.equals("forward")) {
|
||||||
|
directionForward = id;
|
||||||
|
} else if (val.equals("backward")) {
|
||||||
|
directionBackward = id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void completeRouteEncodingRules() {
|
public void completeRouteEncodingRules() {
|
||||||
for(int i = 0; i < routeEncodingRules.size(); i++) {
|
for(int i = 0; i < routeEncodingRules.size(); i++) {
|
||||||
RouteTypeRule rtr = routeEncodingRules.get(i);
|
RouteTypeRule rtr = routeEncodingRules.get(i);
|
||||||
|
|
|
@ -1054,6 +1054,4 @@ public class RouteDataObject {
|
||||||
}
|
}
|
||||||
restrictionsVia[k] = viaWay;
|
restrictionsVia[k] = viaWay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,7 +442,8 @@ public class BinaryRoutePlanner {
|
||||||
segmentDist += squareRootDist(x, y, prevx, prevy);
|
segmentDist += squareRootDist(x, y, prevx, prevy);
|
||||||
|
|
||||||
// 2.1 calculate possible obstacle plus time
|
// 2.1 calculate possible obstacle plus time
|
||||||
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentPoint);
|
|
||||||
|
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentPoint, (dir && !reverseWaySearch));
|
||||||
if (obstacle < 0) {
|
if (obstacle < 0) {
|
||||||
directionAllowed = false;
|
directionAllowed = false;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import gnu.trove.list.array.TIntArrayList;
|
||||||
import gnu.trove.set.hash.TLongHashSet;
|
import gnu.trove.set.hash.TLongHashSet;
|
||||||
|
|
||||||
public class GeneralRouter implements VehicleRouter {
|
public class GeneralRouter implements VehicleRouter {
|
||||||
|
@ -353,33 +354,74 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float defineObstacle(RouteDataObject road, int point) {
|
public float defineObstacle(RouteDataObject road, int point, boolean dir) {
|
||||||
int[] pointTypes = road.getPointTypes(point);
|
int[] pointTypes = road.getPointTypes(point);
|
||||||
if(pointTypes != null) {
|
if(pointTypes != null) {
|
||||||
Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes);
|
Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, dir);
|
||||||
if(obst == null) {
|
if(obst == null) {
|
||||||
obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, pointTypes, 0);
|
int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir);
|
||||||
putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst);
|
obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0);
|
||||||
|
putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst, dir);
|
||||||
}
|
}
|
||||||
return obst;
|
return obst;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIntArrayList filteredRules = new TIntArrayList();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float defineRoutingObstacle(RouteDataObject road, int point) {
|
public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) {
|
||||||
int[] pointTypes = road.getPointTypes(point);
|
int[] pointTypes = road.getPointTypes(point);
|
||||||
if(pointTypes != null){
|
if (pointTypes != null) {
|
||||||
Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes);
|
|
||||||
if(obst == null) {
|
}
|
||||||
obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, pointTypes, 0);
|
if(pointTypes != null) {
|
||||||
putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst);
|
Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, dir);
|
||||||
|
if(obst == null) {
|
||||||
|
int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir );
|
||||||
|
obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0);
|
||||||
|
putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst, dir);
|
||||||
}
|
}
|
||||||
return obst;
|
return obst;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int[] filterDirectionTags(RouteDataObject road, int[] pointTypes, boolean dir) {
|
||||||
|
int wayOppositeDirection = dir ? -1 : 1;
|
||||||
|
int direction = 0;
|
||||||
|
int tdirection = 0;
|
||||||
|
for (int i = 0; i < pointTypes.length; i++) {
|
||||||
|
if (pointTypes[i] == road.region.directionBackward) {
|
||||||
|
direction = -1;
|
||||||
|
} else if(pointTypes[i] == road.region.directionForward) {
|
||||||
|
direction = 1;
|
||||||
|
} else if (pointTypes[i] == road.region.directionTrafficSignalsBackward) {
|
||||||
|
tdirection = -1;
|
||||||
|
} else if(pointTypes[i] == road.region.directionTrafficSignalsForward) {
|
||||||
|
tdirection = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (direction != 0 || tdirection != 0) {
|
||||||
|
TIntArrayList filteredRules = new TIntArrayList();
|
||||||
|
for (int i = 0; i < pointTypes.length; i++) {
|
||||||
|
boolean skip = false;
|
||||||
|
if ((pointTypes[i] == road.region.stopSign || pointTypes[i] == road.region.giveWaySign)
|
||||||
|
&& direction == wayOppositeDirection) {
|
||||||
|
skip = true;
|
||||||
|
} else if (pointTypes[i] == road.region.trafficSignals && direction == wayOppositeDirection) {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
if (!skip) {
|
||||||
|
filteredRules.add(pointTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredRules.toArray();
|
||||||
|
}
|
||||||
|
return pointTypes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) {
|
public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) {
|
||||||
if(!heightObstacles) {
|
if(!heightObstacles) {
|
||||||
|
@ -463,16 +505,20 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
Float sp = getCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road);
|
Float sp = getCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road);
|
||||||
if(sp == null) {
|
if(sp == null) {
|
||||||
sp = getObjContext(RouteDataObjectAttribute.ROAD_PRIORITIES).evaluateFloat(road, 1f);
|
sp = getObjContext(RouteDataObjectAttribute.ROAD_PRIORITIES).evaluateFloat(road, 1f);
|
||||||
putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp);
|
putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp, false);
|
||||||
}
|
}
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val) {
|
private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val) {
|
||||||
putCache(attr, road.region, road.types, val);
|
putCache(attr, road.region, road.types, val, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, Float val) {
|
private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val, boolean extra) {
|
||||||
|
putCache(attr, road.region, road.types, val, extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, Float val, boolean extra) {
|
||||||
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
|
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
|
||||||
if (USE_CACHE) {
|
if (USE_CACHE) {
|
||||||
Map<IntHolder, Float> rM = ch.get(reg);
|
Map<IntHolder, Float> rM = ch.get(reg);
|
||||||
|
@ -480,40 +526,56 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
rM = new HashMap<IntHolder, Float>();
|
rM = new HashMap<IntHolder, Float>();
|
||||||
ch.put(reg, rM);
|
ch.put(reg, rM);
|
||||||
}
|
}
|
||||||
rM.put(new IntHolder(types), val);
|
rM.put(new IntHolder(types, extra), val);
|
||||||
}
|
}
|
||||||
TIMER += System.nanoTime();
|
TIMER += System.nanoTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntHolder {
|
class IntHolder {
|
||||||
private final int[] array;
|
private final int[] array;
|
||||||
IntHolder(int[] ts) { array = ts; }
|
private final boolean extra;
|
||||||
@Override public int hashCode() { return Arrays.hashCode(array); }
|
|
||||||
@Override public boolean equals(Object other) {
|
IntHolder(int[] ts, boolean extra) {
|
||||||
if (array == other) { return true; }
|
array = ts;
|
||||||
if (! (other instanceof IntHolder) ) {
|
this.extra = extra;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
//noinspection unchecked
|
@Override
|
||||||
return Arrays.equals(array, ((IntHolder) other).array);
|
public int hashCode() {
|
||||||
}
|
return Arrays.hashCode(array) + (extra ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (array == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(other instanceof IntHolder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (((IntHolder) other).extra != this.extra) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// noinspection unchecked
|
||||||
|
return Arrays.equals(array, ((IntHolder) other).array);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Float getCache(RouteDataObjectAttribute attr, RouteDataObject road) {
|
private Float getCache(RouteDataObjectAttribute attr, RouteDataObject road) {
|
||||||
return getCache(attr, road.region, road.types);
|
return getCache(attr, road.region, road.types, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Float getCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types) {
|
private Float getCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, boolean extra) {
|
||||||
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
|
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
|
||||||
TIMER -= System.nanoTime();
|
// TIMER -= System.nanoTime();
|
||||||
if (USE_CACHE) {
|
if (USE_CACHE) {
|
||||||
Map<IntHolder, Float> rM = ch.get(reg);
|
Map<IntHolder, Float> rM = ch.get(reg);
|
||||||
if (rM == null) {
|
if (rM == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Float vl = rM.get(new IntHolder(types));
|
Float vl = rM.get(new IntHolder(types, extra));
|
||||||
if(vl != null) {
|
if(vl != null) {
|
||||||
TIMER += System.nanoTime();
|
// TIMER += System.nanoTime();
|
||||||
return vl;
|
return vl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ public class RouteResultPreparation {
|
||||||
double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next),
|
double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next),
|
||||||
road.getPoint31YTile(next));
|
road.getPoint31YTile(next));
|
||||||
distance += d;
|
distance += d;
|
||||||
double obstacle = ctx.getRouter().defineObstacle(road, j);
|
double obstacle = ctx.getRouter().defineObstacle(road, j, plus);
|
||||||
if (obstacle < 0) {
|
if (obstacle < 0) {
|
||||||
obstacle = 0;
|
obstacle = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public interface VehicleRouter {
|
||||||
/**
|
/**
|
||||||
* return delay in seconds (0 no obstacles)
|
* return delay in seconds (0 no obstacles)
|
||||||
*/
|
*/
|
||||||
public float defineObstacle(RouteDataObject road, int point);
|
public float defineObstacle(RouteDataObject road, int point, boolean dir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return delay in seconds for height obstacles
|
* return delay in seconds for height obstacles
|
||||||
|
@ -40,7 +40,7 @@ public interface VehicleRouter {
|
||||||
/**
|
/**
|
||||||
* return delay in seconds (0 no obstacles)
|
* return delay in seconds (0 no obstacles)
|
||||||
*/
|
*/
|
||||||
public float defineRoutingObstacle(RouteDataObject road, int point);
|
public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return routing speed in m/s for vehicle for specified road
|
* return routing speed in m/s for vehicle for specified road
|
||||||
|
|
3
OsmAnd-java/src/test/resources/.gitignore
vendored
3
OsmAnd-java/src/test/resources/.gitignore
vendored
|
@ -3,4 +3,5 @@
|
||||||
/search/*
|
/search/*
|
||||||
*.obf
|
*.obf
|
||||||
*.osm
|
*.osm
|
||||||
phrases.xml
|
phrases.xml
|
||||||
|
*.obf.gz
|
||||||
|
|
Loading…
Reference in a new issue