OsmAnd/OsmAnd-java/src/net/osmand/binary/RouteDataObject.java

371 lines
8.5 KiB
Java
Raw Normal View History

package net.osmand.binary;
import gnu.trove.map.hash.TIntObjectHashMap;
import java.text.MessageFormat;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule;
2014-02-02 14:06:09 +01:00
import net.osmand.util.Algorithms;
public class RouteDataObject {
/*private */static final int RESTRICTION_SHIFT = 3;
/*private */static final int RESTRICTION_MASK = 7;
public final RouteRegion region;
// all these arrays supposed to be immutable!
// These fields accessible from C++
public int[] types;
public int[] pointsX;
public int[] pointsY;
public long[] restrictions;
public int[][] pointTypes;
public long id;
public TIntObjectHashMap<String> names;
public final static float NONE_MAX_SPEED = 40f;
public RouteDataObject(RouteRegion region) {
this.region = region;
}
public RouteDataObject(RouteRegion region, int[] nameIds, String[] nameValues) {
this.region = region;
if (nameIds.length > 0) {
names = new TIntObjectHashMap<String>();
}
for (int i = 0; i < nameIds.length; i++) {
names.put(nameIds[i], nameValues[i]);
}
}
public RouteDataObject(RouteDataObject copy) {
this.region = copy.region;
this.pointsX = copy.pointsX;
this.pointsY = copy.pointsY;
this.types = copy.types;
this.names = copy.names;
this.restrictions = copy.restrictions;
this.pointTypes = copy.pointTypes;
this.id = copy.id;
}
public long getId() {
return id;
}
public String getName(){
if(names != null ) {
return names.get(region.nameTypeRule);
}
return null;
}
public TIntObjectHashMap<String> getNames() {
return names;
}
public String getRef(){
if(names != null ) {
return names.get(region.refTypeRule);
}
return null;
}
public String getDestinationName(){
if(names != null ) {
return names.get(region.destinationTypeRule);
}
return null;
}
public int getPoint31XTile(int i) {
return pointsX[i];
}
public int getPoint31YTile(int i) {
return pointsY[i];
}
public int getPointsLength() {
return pointsX.length;
}
public int getRestrictionLength() {
return restrictions == null ? 0 : restrictions.length;
}
public int getRestrictionType(int i) {
return (int) (restrictions[i] & RESTRICTION_MASK);
}
public long getRestrictionId(int i) {
return restrictions[i] >> RESTRICTION_SHIFT;
}
public void insert(int pos, int x31, int y31) {
int[] opointsX = pointsX;
int[] opointsY = pointsY;
int[][] opointTypes = pointTypes;
pointsX = new int[pointsX.length + 1];
pointsY = new int[pointsY.length + 1];
boolean insTypes = this.pointTypes != null && this.pointTypes.length > pos;
if (insTypes) {
pointTypes = new int[opointTypes.length + 1][];
}
int i = 0;
for (; i < pos; i++) {
pointsX[i] = opointsX[i];
pointsY[i] = opointsY[i];
if (insTypes) {
pointTypes[i] = opointTypes[i];
}
}
pointsX[i] = x31;
pointsY[i] = y31;
if (insTypes) {
pointTypes[i] = null;
}
for (i = i + 1; i < pointsX.length; i++) {
pointsX[i] = opointsX[i - 1];
pointsY[i] = opointsY[i - 1];
if (insTypes && i < pointTypes.length) {
pointTypes[i] = opointTypes[i - 1];
}
}
}
public int[] getPointTypes(int ind) {
if (pointTypes == null || ind >= pointTypes.length) {
return null;
}
return pointTypes[ind];
}
public int[] getTypes() {
return types;
}
public float getMaximumSpeed(){
int sz = types.length;
2013-09-12 01:24:09 +02:00
float maxSpeed = 0;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
2013-09-12 01:24:09 +02:00
float mx = r.maxSpeed();
if (mx > 0) {
maxSpeed = mx;
// conditional has priority
if(r.conditional()) {
break;
}
}
}
2013-09-12 01:24:09 +02:00
return maxSpeed ;
}
2014-02-02 14:06:09 +01:00
public static float parseSpeed(String v, float def) {
if(v.equals("none")) {
return RouteDataObject.NONE_MAX_SPEED;
} else {
int i = Algorithms.findFirstNumberEndIndex(v);
if (i > 0) {
float f = Float.parseFloat(v.substring(0, i));
f /= 3.6; // km/h -> m/s
if (v.contains("mph")) {
f *= 1.6;
}
return f;
}
}
return def;
}
public static float parseLength(String v, float def) {
// 14"10' not supported
int i = Algorithms.findFirstNumberEndIndex(v);
if (i > 0) {
float f = Float.parseFloat(v.substring(0, i));
if (v.contains("\"") || v.contains("ft")) {
// foot to meters
f *= 0.3048;
}
return f;
}
return def;
}
public static float parseWeightInTon(String v, float def) {
int i = Algorithms.findFirstNumberEndIndex(v);
if (i > 0) {
float f = Float.parseFloat(v.substring(0, i));
if (v.contains("\"") || v.contains("lbs")) {
// lbs -> kg -> ton
f = (f * 0.4535f) / 1000f;
}
return f;
}
return def;
}
public boolean loop(){
return pointsX[0] == pointsX[pointsX.length - 1] && pointsY[0] == pointsY[pointsY.length - 1] ;
}
public boolean roundabout(){
int sz = types.length;
for(int i=0; i<sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if(r.roundabout()) {
return true;
} else if(r.onewayDirection() != 0 && loop()) {
return true;
}
}
return false;
}
2013-10-29 21:13:57 +01:00
public boolean tunnel(){
int sz = types.length;
for(int i=0; i<sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if(r.getTag().equals("tunnel") && r.getValue().equals("yes")) {
return true;
}
if(r.getTag().equals("layer") && r.getValue().equals("-1")) {
return true;
}
}
return false;
}
public int getOneway() {
int sz = types.length;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if (r.onewayDirection() != 0) {
return r.onewayDirection();
} else if (r.roundabout()) {
return 1;
}
}
return 0;
}
public String getRoute() {
int sz = types.length;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if ("route".equals(r.getTag())) {
return r.getValue();
}
}
return null;
}
public String getHighway() {
return getHighway(types, region);
}
2014-10-02 14:14:34 +02:00
public String getValue(String tag) {
for (int i = 0; i < types.length; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if (r.getTag().equals(tag)) {
return r.getValue();
}
}
return null;
}
public static String getHighway(int[] types, RouteRegion region) {
String highway = null;
int sz = types.length;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
highway = r.highwayRoad();
if (highway != null) {
break;
}
}
return highway;
}
public int getLanes() {
int sz = types.length;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
int ln = r.lanes();
if (ln > 0) {
return ln;
}
}
return -1;
}
public double directionRoute(int startPoint, boolean plus) {
// same goes to C++
// Victor : the problem to put more than 5 meters that BinaryRoutePlanner will treat
// 2 consequent Turn Right as UT and here 2 points will have same turn angle
// So it should be fix in both places
return directionRoute(startPoint, plus, 5);
}
2013-11-26 16:23:05 +01:00
public double distance(int startPoint, int endPoint) {
if(startPoint > endPoint) {
int k = endPoint;
endPoint = startPoint;
startPoint = k;
}
double d = 0;
for(int k = startPoint; k < endPoint && k < getPointsLength() -1; k++) {
int x = getPoint31XTile(k);
int y = getPoint31YTile(k);
int kx = getPoint31XTile(k + 1);
int ky = getPoint31YTile(k + 1);
d += simplifyDistance(kx, ky, x, y);
}
return d;
}
// Gives route direction of EAST degrees from NORTH ]-PI, PI]
public double directionRoute(int startPoint, boolean plus, float dist) {
int x = getPoint31XTile(startPoint);
int y = getPoint31YTile(startPoint);
int nx = startPoint;
int px = x;
int py = y;
double total = 0;
do {
if (plus) {
nx++;
if (nx >= getPointsLength()) {
break;
}
} else {
nx--;
if (nx < 0) {
break;
}
}
px = getPoint31XTile(nx);
py = getPoint31YTile(nx);
// translate into meters
2013-11-26 16:23:05 +01:00
total += simplifyDistance(x, y, px, py);
} while (total < dist);
return -Math.atan2( x - px, y - py );
}
2013-11-26 16:23:05 +01:00
private double simplifyDistance(int x, int y, int px, int py) {
return Math.abs(px - x) * 0.011d + Math.abs(py - y) * 0.01863d;
}
2014-10-02 14:14:34 +02:00
@Override
public String toString() {
String name = getName();
String rf = getRef();
return MessageFormat.format("Road id {0} name {1} ref {2}", getId()+"", name == null ? "" : name, rf == null ? "" : rf);
}
}