Initial srtm routing
This commit is contained in:
parent
6aa4c11969
commit
aaf049f381
6 changed files with 123 additions and 62 deletions
|
@ -217,6 +217,7 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
public String getPartName() {
|
public String getPartName() {
|
||||||
return "Routing";
|
return "Routing";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getFieldNumber() {
|
public int getFieldNumber() {
|
||||||
return OsmandOdb.OsmAndStructure.ROUTINGINDEX_FIELD_NUMBER;
|
return OsmandOdb.OsmAndStructure.ROUTINGINDEX_FIELD_NUMBER;
|
||||||
|
|
|
@ -16,6 +16,7 @@ import net.sf.junidecode.Junidecode;
|
||||||
public class RouteDataObject {
|
public class RouteDataObject {
|
||||||
/*private */static final int RESTRICTION_SHIFT = 3;
|
/*private */static final int RESTRICTION_SHIFT = 3;
|
||||||
/*private */static final int RESTRICTION_MASK = 7;
|
/*private */static final int RESTRICTION_MASK = 7;
|
||||||
|
public static int HEIGHT_UNDEFINED = -80000;
|
||||||
|
|
||||||
public final RouteRegion region;
|
public final RouteRegion region;
|
||||||
// all these arrays supposed to be immutable!
|
// all these arrays supposed to be immutable!
|
||||||
|
@ -31,6 +32,8 @@ public class RouteDataObject {
|
||||||
public TIntObjectHashMap<String> names;
|
public TIntObjectHashMap<String> names;
|
||||||
public final static float NONE_MAX_SPEED = 40f;
|
public final static float NONE_MAX_SPEED = 40f;
|
||||||
public int[] nameIds;
|
public int[] nameIds;
|
||||||
|
// mixed array [0, height, cumulative_distance height, cumulative_distance, height, ...] - length is length(points)*2
|
||||||
|
public float[] heightDistanceArray = null;
|
||||||
|
|
||||||
public RouteDataObject(RouteRegion region) {
|
public RouteDataObject(RouteRegion region) {
|
||||||
this.region = region;
|
this.region = region;
|
||||||
|
@ -59,6 +62,73 @@ public class RouteDataObject {
|
||||||
this.pointNameTypes = copy.pointNameTypes;
|
this.pointNameTypes = copy.pointNameTypes;
|
||||||
this.id = copy.id;
|
this.id = copy.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float[] calculateHeightArray() {
|
||||||
|
if(heightDistanceArray != null) {
|
||||||
|
return heightDistanceArray;
|
||||||
|
}
|
||||||
|
int startHeight = Algorithms.parseIntSilently(getValue("osmand_ele_start"), HEIGHT_UNDEFINED);
|
||||||
|
int endHeight = Algorithms.parseIntSilently(getValue("osmand_ele_end"), startHeight);
|
||||||
|
if(startHeight == HEIGHT_UNDEFINED) {
|
||||||
|
heightDistanceArray = new float[0];
|
||||||
|
return heightDistanceArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
heightDistanceArray = new float[2*getPointsLength()];
|
||||||
|
double plon = 0;
|
||||||
|
double plat = 0;
|
||||||
|
int prevHeight = startHeight;
|
||||||
|
for(int k = 0; k < getPointsLength(); k++) {
|
||||||
|
double lon = MapUtils.get31LongitudeX(getPoint31XTile(k));
|
||||||
|
double lat = MapUtils.get31LatitudeY(getPoint31YTile(k));
|
||||||
|
if(k > 0) {
|
||||||
|
double dd = MapUtils.getDistance(plat, plon, lat, lon);
|
||||||
|
int height = HEIGHT_UNDEFINED;
|
||||||
|
if(k == getPointsLength() - 1) {
|
||||||
|
height = endHeight;
|
||||||
|
} else {
|
||||||
|
int[] tps = getPointTypes(k);
|
||||||
|
if (tps != null) {
|
||||||
|
for (int id : tps) {
|
||||||
|
RouteTypeRule rt = region.quickGetEncodingRule(id);
|
||||||
|
if (rt.getTag().equals("osmand_ele_asc")) {
|
||||||
|
height = (int) (prevHeight + Float.parseFloat(rt.getValue()));
|
||||||
|
break;
|
||||||
|
} else if (rt.getTag().equals("osmand_ele_desc")) {
|
||||||
|
height = (int) (prevHeight - Float.parseFloat(rt.getValue()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heightDistanceArray[2*k] = (float) dd;
|
||||||
|
heightDistanceArray[2*k+1] = height;
|
||||||
|
if(height != HEIGHT_UNDEFINED) {
|
||||||
|
// interpolate undefined
|
||||||
|
double totalDistance = dd;
|
||||||
|
int startUndefined = k;
|
||||||
|
while(startUndefined - 1 >= 0 && heightDistanceArray[2*(startUndefined - 1)+1] == HEIGHT_UNDEFINED) {
|
||||||
|
startUndefined --;
|
||||||
|
totalDistance += heightDistanceArray[2*(startUndefined)];
|
||||||
|
}
|
||||||
|
if(totalDistance > 0) {
|
||||||
|
double angle = (height - prevHeight) / totalDistance;
|
||||||
|
for(int j = startUndefined; j < k; j++) {
|
||||||
|
heightDistanceArray[2*j+1] = (float) ((heightDistanceArray[2*j] * angle) + heightDistanceArray[2*j-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
heightDistanceArray[0] = 0;
|
||||||
|
heightDistanceArray[1] = startHeight;
|
||||||
|
}
|
||||||
|
plat = lat;
|
||||||
|
plon = lon;
|
||||||
|
}
|
||||||
|
return heightDistanceArray;
|
||||||
|
}
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -445,10 +445,16 @@ public class BinaryRoutePlanner {
|
||||||
if (obstacle < 0) {
|
if (obstacle < 0) {
|
||||||
directionAllowed = false;
|
directionAllowed = false;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
double heightObstacle = ctx.getRouter().defineHeightObstacle(road, !reverseWaySearch ? prevInd : segmentPoint,
|
||||||
|
!reverseWaySearch ? segmentPoint : prevInd, segmentDist);
|
||||||
|
if(heightObstacle > 0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
boolean alreadyVisited = checkIfOppositeSegmentWasVisited(ctx, reverseWaySearch, graphSegments, segment, oppositeSegments,
|
boolean alreadyVisited = checkIfOppositeSegmentWasVisited(ctx, reverseWaySearch, graphSegments, segment, oppositeSegments,
|
||||||
segmentPoint, segmentDist, obstaclesTime);
|
segmentPoint, segmentDist, obstaclesTime);
|
||||||
obstaclesTime += obstacle;
|
obstaclesTime += obstacle;
|
||||||
|
obstaclesTime += heightObstacle;
|
||||||
if (alreadyVisited) {
|
if (alreadyVisited) {
|
||||||
directionAllowed = false;
|
directionAllowed = false;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
|
|
||||||
private static final float CAR_SHORTEST_DEFAULT_SPEED = 55/3.6f;
|
private static final float CAR_SHORTEST_DEFAULT_SPEED = 55/3.6f;
|
||||||
public static final String USE_SHORTEST_WAY = "short_way";
|
public static final String USE_SHORTEST_WAY = "short_way";
|
||||||
|
public static final String USE_HEIGHT_OBSTACLES = "height_obstacles";
|
||||||
public static final String AVOID_FERRIES = "avoid_ferries";
|
public static final String AVOID_FERRIES = "avoid_ferries";
|
||||||
public static final String AVOID_TOLL = "avoid_toll";
|
public static final String AVOID_TOLL = "avoid_toll";
|
||||||
public static final String AVOID_MOTORWAY = "avoid_motorway";
|
public static final String AVOID_MOTORWAY = "avoid_motorway";
|
||||||
|
@ -39,6 +40,7 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
private final Map<String, BitSet> tagRuleMask;
|
private final Map<String, BitSet> tagRuleMask;
|
||||||
private final ArrayList<Object> ruleToValue;
|
private final ArrayList<Object> ruleToValue;
|
||||||
private boolean shortestRoute;
|
private boolean shortestRoute;
|
||||||
|
private boolean heightObstacles;
|
||||||
|
|
||||||
private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>();
|
private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>();
|
||||||
|
|
||||||
|
@ -129,6 +131,7 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
objectAttributes[i] = new RouteAttributeContext(parent.objectAttributes[i], params);
|
objectAttributes[i] = new RouteAttributeContext(parent.objectAttributes[i], params);
|
||||||
}
|
}
|
||||||
shortestRoute = params.containsKey(USE_SHORTEST_WAY) && parseSilentBoolean(params.get(USE_SHORTEST_WAY), false);
|
shortestRoute = params.containsKey(USE_SHORTEST_WAY) && parseSilentBoolean(params.get(USE_SHORTEST_WAY), false);
|
||||||
|
heightObstacles = params.containsKey(USE_HEIGHT_OBSTACLES) && parseSilentBoolean(params.get(USE_HEIGHT_OBSTACLES), false);
|
||||||
if(shortestRoute) {
|
if(shortestRoute) {
|
||||||
maxDefaultSpeed = Math.min(CAR_SHORTEST_DEFAULT_SPEED, maxDefaultSpeed);
|
maxDefaultSpeed = Math.min(CAR_SHORTEST_DEFAULT_SPEED, maxDefaultSpeed);
|
||||||
}
|
}
|
||||||
|
@ -284,6 +287,39 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex, float distance) {
|
||||||
|
if(!heightObstacles) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
float[] heightArray = road.calculateHeightArray();
|
||||||
|
if(heightArray == null || heightArray.length == 0 ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
int knext;
|
||||||
|
int[] types = new int[0];
|
||||||
|
RouteAttributeContext objContext = getObjContext(RouteDataObjectAttribute.OBSTACLE_SRTM_ALT_SPEED);
|
||||||
|
for(int k = startIndex; k != endIndex; k = knext) {
|
||||||
|
knext = startIndex < endIndex ? k + 1 : k - 1;
|
||||||
|
double dist = Math.abs(heightArray[2 * k] - heightArray[2 * knext]) ;
|
||||||
|
double diff = heightArray[2 * knext + 1] - heightArray[2 * k + 1] ;
|
||||||
|
if(diff > 0 && dist > 0) {
|
||||||
|
double incl = diff / dist;
|
||||||
|
int percentIncl = (int) (incl * 100);
|
||||||
|
percentIncl = (percentIncl + 2)/ 3 * 3 - 2; // 1, 4, 7, 10, .
|
||||||
|
if(percentIncl > 0) {
|
||||||
|
// IMPROVEMENT: register with value and cache parsed value
|
||||||
|
objContext.paramContext.vars.put("incline", percentIncl + "");
|
||||||
|
sum += objContext.evaluateFloat(road.region, types, 0) * diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int isOneWay(RouteDataObject road) {
|
public int isOneWay(RouteDataObject road) {
|
||||||
return getObjContext(RouteDataObjectAttribute.ONEWAY).evaluateInt(road, 0);
|
return getObjContext(RouteDataObjectAttribute.ONEWAY).evaluateInt(road, 0);
|
||||||
|
@ -299,6 +335,7 @@ public class GeneralRouter implements VehicleRouter {
|
||||||
return Math.min(defineVehicleSpeed(road), maxDefaultSpeed);
|
return Math.min(defineVehicleSpeed(road), maxDefaultSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float defineVehicleSpeed(RouteDataObject road) {
|
public float defineVehicleSpeed(RouteDataObject road) {
|
||||||
return getObjContext(RouteDataObjectAttribute.ROAD_SPEED) .evaluateFloat(road, getMinDefaultSpeed());
|
return getObjContext(RouteDataObjectAttribute.ROAD_SPEED) .evaluateFloat(road, getMinDefaultSpeed());
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package net.osmand.router;
|
package net.osmand.router;
|
||||||
|
|
||||||
|
|
||||||
import gnu.trove.list.array.TIntArrayList;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -27,7 +25,6 @@ public class RouteSegmentResult {
|
||||||
private String description = "";
|
private String description = "";
|
||||||
// this make not possible to make turns in between segment result for now
|
// this make not possible to make turns in between segment result for now
|
||||||
private TurnType turnType;
|
private TurnType turnType;
|
||||||
public static int HEIGHT_UNDEFINED = -80000;
|
|
||||||
|
|
||||||
|
|
||||||
public RouteSegmentResult(RouteDataObject object, int startPointIndex, int endPointIndex) {
|
public RouteSegmentResult(RouteDataObject object, int startPointIndex, int endPointIndex) {
|
||||||
|
@ -38,70 +35,13 @@ public class RouteSegmentResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[] getHeightValues() {
|
public float[] getHeightValues() {
|
||||||
int startHeight = Algorithms.parseIntSilently(object.getValue("osmand_ele_start"), HEIGHT_UNDEFINED);
|
float[] pf = object.calculateHeightArray();
|
||||||
int endHeight = Algorithms.parseIntSilently(object.getValue("osmand_ele_end"), startHeight);
|
if(pf == null || pf.length == 0) {
|
||||||
if(startHeight == HEIGHT_UNDEFINED) {
|
|
||||||
return new float[0];
|
return new float[0];
|
||||||
}
|
}
|
||||||
TIntArrayList list = new TIntArrayList();
|
|
||||||
float[] pf = new float[2*object.getPointsLength()];
|
|
||||||
double dist = 0;
|
|
||||||
double plon = 0;
|
|
||||||
double plat = 0;
|
|
||||||
int prevHeight = startHeight;
|
|
||||||
for(int k = 0; k < object.getPointsLength(); k++) {
|
|
||||||
double lon = MapUtils.get31LongitudeX(object.getPoint31XTile(k));
|
|
||||||
double lat = MapUtils.get31LatitudeY(object.getPoint31YTile(k));
|
|
||||||
if(k > 0) {
|
|
||||||
double dd = MapUtils.getDistance(plat, plon, lat, lon);
|
|
||||||
int height = HEIGHT_UNDEFINED;
|
|
||||||
if(k == object.getPointsLength() - 1) {
|
|
||||||
height = endHeight;
|
|
||||||
} else {
|
|
||||||
int[] tps = object.getPointTypes(k);
|
|
||||||
if (tps != null) {
|
|
||||||
for (int id : tps) {
|
|
||||||
RouteTypeRule rt = object.region.quickGetEncodingRule(id);
|
|
||||||
if (rt.getTag().equals("osmand_ele_asc")) {
|
|
||||||
height = (int) (prevHeight + Float.parseFloat(rt.getValue()));
|
|
||||||
break;
|
|
||||||
} else if (rt.getTag().equals("osmand_ele_desc")) {
|
|
||||||
height = (int) (prevHeight - Float.parseFloat(rt.getValue()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pf[2*k] = (float) dd;
|
|
||||||
pf[2*k+1] = height;
|
|
||||||
if(height != HEIGHT_UNDEFINED) {
|
|
||||||
// interpolate undefined
|
|
||||||
double totalDistance = dd;
|
|
||||||
int startUndefined = k;
|
|
||||||
while(startUndefined - 1 >= 0 && pf[2*(startUndefined - 1)+1] == HEIGHT_UNDEFINED) {
|
|
||||||
startUndefined --;
|
|
||||||
totalDistance += pf[2*(startUndefined)];
|
|
||||||
}
|
|
||||||
if(totalDistance > 0) {
|
|
||||||
double angle = (height - prevHeight) / totalDistance;
|
|
||||||
for(int j = startUndefined; j < k; j++) {
|
|
||||||
pf[2*j+1] = (float) ((pf[2*j] * angle) + pf[2*j-1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevHeight = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
pf[0] = 0;
|
|
||||||
pf[1] = startHeight;
|
|
||||||
}
|
|
||||||
plat = lat;
|
|
||||||
plon = lon;
|
|
||||||
}
|
|
||||||
boolean reverse = startPointIndex > endPointIndex;
|
boolean reverse = startPointIndex > endPointIndex;
|
||||||
int st = Math.min(startPointIndex, endPointIndex);
|
int st = Math.min(startPointIndex, endPointIndex);
|
||||||
int end = Math.max(startPointIndex, endPointIndex);
|
int end = Math.max(startPointIndex, endPointIndex);
|
||||||
|
|
||||||
float[] res = new float[(end - st + 1) * 2];
|
float[] res = new float[(end - st + 1) * 2];
|
||||||
for (int k = 0; k < res.length / 2; k++) {
|
for (int k = 0; k < res.length / 2; k++) {
|
||||||
if (k == 0) {
|
if (k == 0) {
|
||||||
|
|
|
@ -32,6 +32,11 @@ public interface VehicleRouter {
|
||||||
*/
|
*/
|
||||||
public float defineObstacle(RouteDataObject road, int point);
|
public float defineObstacle(RouteDataObject road, int point);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return delay in seconds for height obstacles
|
||||||
|
*/
|
||||||
|
public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex, float distance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return delay in seconds (0 no obstacles)
|
* return delay in seconds (0 no obstacles)
|
||||||
*/
|
*/
|
||||||
|
@ -78,5 +83,7 @@ public interface VehicleRouter {
|
||||||
|
|
||||||
|
|
||||||
public VehicleRouter build(Map<String, String> params);
|
public VehicleRouter build(Map<String, String> params);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue