osmdroid API解读(十)
osmdroid-android org.osmdroid.util.constants包
1. GeoConstants
地理常数
public interface GeoConstants {
public static final int RADIUS_EARTH_METERS = 6378137; // 赤道半径
public static final double METERS_PER_STATUTE_MILE = 1609.344; //每法定英里米数
public static final double METERS_PER_NAUTICAL_MILE = 1852; // 每海里米数
public static final double FEET_PER_METER = 3.2808399; // 每米英尺数
public static final int EQUATORCIRCUMFENCE = (int) (2 * Math.PI * RADIUS_EARTH_METERS);//赤道周长
}
osmdroid-android org.osmdroid.util包
二维距离计算工具
public class Distance {
//计算两点间距离
public static double getSquaredDistanceToPoint(
final double pFromX, final double pFromY, final double pToX, final double pToY) {
final double dX = pFromX - pToX;
final double dY = pFromY - pToY;
return dX * dX + dY * dY;
}
//计算点到线的距离
public static double getSquaredDistanceToLine(
final double pFromX, final double pFromY,
final double pAX, final double pAY, final double pBX, final double pBY
) {
if (pAX == pBX && pAY == pBY) {
return getSquaredDistanceToPoint(pAX, pAY, pFromX, pFromY);
}
final double cross = crossProduct(pAX, pAY, pBX, pBY, pFromX, pFromY);
return cross * cross / getSquaredDistanceToPoint(pAX, pAY, pBX, pBY);
}
//计算点到线段的距离
public static double getSquaredDistanceToSegment(
final double pFromX, final double pFromY,
final double pAX, final double pAY, final double pBX, final double pBY
) {
if (pAX == pBX && pAY == pBY) {
return getSquaredDistanceToPoint(pAX, pAY, pFromX, pFromY);
}
double dot = dotProduct(pAX, pAY, pBX, pBY, pFromX, pFromY);
if (dot > 0) {
return getSquaredDistanceToPoint(pFromX, pFromY, pBX, pBY);
}
dot = dotProduct(pBX, pBY, pAX, pAY, pFromX, pFromY);
if (dot > 0) {
return getSquaredDistanceToPoint(pFromX, pFromY, pAX, pAY);
}
final double cross = crossProduct(pAX, pAY, pBX, pBY, pFromX, pFromY);
return cross * cross / getSquaredDistanceToPoint(pAX, pAY, pBX, pBY);
}
//计算叉乘AB x AC
private static double crossProduct(
final double pAX, final double pAY, final double pBX, final double pBY,
final double pCX, final double pCY) {
return (pBX - pAX) * (pCY - pAY) - (pBY - pAY) * (pCX - pAX);
}
//计算点乘AB . AC
private static double dotProduct(
final double pAX, final double pAY, final double pBX, final double pBY,
final double pCX, final double pCY) {
return (pBX - pAX) * (pCX - pBX) + (pBY - pAY) * (pCY - pBY);
}
}
2. MyMath
public class MyMath implements MathConstants {
private MyMath() {
}
//Gudermann逆转换
public static double gudermannInverse(final double aLatitude) {
return Math.log(Math.tan(PI_4 + (DEG2RAD * aLatitude / 2)));
}
//Gudermann转换
public static double gudermann(final double y) {
return RAD2DEG * Math.atan(Math.sinh(y));
}
//取余
public static int mod(int number, final int modulus) {
if (number > 0)
return number % modulus;
while (number < 0)
number += modulus;
return number;
}
//转换为比pValue小的最大整数
public static long floorToLong(final double pValue) {
final long result = (long) pValue;
if (result <= pValue) {
return result;
}
return result - 1;
}
//转换为比pValue小的最大整数
public static int floorToInt(final double pValue) {
final int result = (int) pValue;
if (result <= pValue) {
return result;
}
return result - 1;
}
}
3. PointL
长整型点
public class PointL {
public long x;
public long y;
...
}
4. RectL
长整型矩形
public class RectL {
public long left;
public long top;
public long right;
public long bottom;
...
}
5. GeoPoint
由经度、纬度、高程描述的地理点
public class GeoPoint implements IGeoPoint, MathConstants, GeoConstants, Parcelable, Serializable, Cloneable {
static final long serialVersionUID = 1L;
private double mLongitude;//经度
private double mLatitude;//纬度
private double mAltitude;//高程
@Deprecated
public GeoPoint(final int aLatitudeE6, final int aLongitudeE6) {
this.mLatitude = aLatitudeE6 / 1E6;
this.mLongitude = aLongitudeE6 / 1E6;
}
@Deprecated
public GeoPoint(final int aLatitudeE6, final int aLongitudeE6, final int aAltitude) {
this.mLatitude = aLatitudeE6 / 1E6;
this.mLongitude = aLongitudeE6 / 1E6;
this.mAltitude = aAltitude;
}
public GeoPoint(final double aLatitude, final double aLongitude) {
this.mLatitude = aLatitude;
this.mLongitude = aLongitude;
}
public GeoPoint(final double aLatitude, final double aLongitude, final double aAltitude) {
this.mLatitude = aLatitude;
this.mLongitude = aLongitude;
this.mAltitude = aAltitude;
}
public GeoPoint(final Location aLocation) {
this(aLocation.getLatitude(), aLocation.getLongitude(), aLocation.getAltitude());
}
public GeoPoint(final GeoPoint aGeopoint) {
this.mLatitude = aGeopoint.mLatitude;
this.mLongitude = aGeopoint.mLongitude;
this.mAltitude = aGeopoint.mAltitude;
}
//将字符串转化为GeoPoint对象
public static GeoPoint fromDoubleString(final String s, final char spacer) {
...
}
//将反向的字符串转换为GeoPoint对象
public static GeoPoint fromInvertedDoubleString(final String s, final char spacer) {
...
}
//将整型的字符串转换为GeoPoint对象
public static GeoPoint fromIntString(final String s) {
...
}
@Override
public double getLongitude() {
return this.mLongitude;
}
@Override
public double getLatitude() {
return this.mLatitude;
}
public double getAltitude() {
return this.mAltitude;
}
public void setLatitude(final double aLatitude) { this.mLatitude = aLatitude; }
public void setLongitude(final double aLongitude) { this.mLongitude = aLongitude; }
public void setAltitude(final double aAltitude) {
this.mAltitude = aAltitude;
}
public void setCoords(final double aLatitude, final double aLongitude) {
this.mLatitude = aLatitude;
this.mLongitude = aLongitude;
}
//克隆一个GeoPoint对象
@Override
public GeoPoint clone() {
return new GeoPoint(this.mLatitude, this.mLongitude, this.mAltitude);
}
//转换为整数型字符串
public String toIntString() {
return new StringBuilder().
append(((int)(this.mLatitude*1E6))).
append(",").
append(((int)(this.mLongitude*1E6))).
append(",").
append((int)(this.mAltitude))
.toString();
}
//转换为字符串
@Override
public String toString() {
return new StringBuilder().append(this.mLatitude).append(",").append(this.mLongitude).append(",").append(this.mAltitude)
.toString();
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
final GeoPoint rhs = (GeoPoint) obj;
return rhs.mLatitude == this.mLatitude && rhs.mLongitude == this.mLongitude && rhs.mAltitude == this.mAltitude;
}
@Override
public int hashCode() {
return 37 * (17 * (int)(mLatitude*1E-6) + (int)(mLongitude*1E-6)) + (int)mAltitude;
}
//求两点间距离(整数型)
@Deprecated
public int distanceTo(final IGeoPoint other) {
return (int) (distanceToAsDouble(other));
}
//求两点间double类型距离
public double distanceToAsDouble(final IGeoPoint other) {
final double lat1 = DEG2RAD * getLatitude();
final double lat2 = DEG2RAD * other.getLatitude();
final double lon1 = DEG2RAD * getLongitude();
final double lon2 = DEG2RAD * other.getLongitude();
return RADIUS_EARTH_METERS * 2 * Math.asin(Math.min(1, Math.sqrt(
Math.pow(Math.sin((lat2 - lat1) / 2), 2)
+ Math.cos(lat1) * Math.cos(lat2)
* Math.pow(Math.sin((lon2 - lon1) / 2), 2)
)));
}
//角度差
public double bearingTo(final IGeoPoint other) {
final double lat1 = Math.toRadians(this.mLatitude);
final double long1 = Math.toRadians(this.mLongitude);
final double lat2 = Math.toRadians(other.getLatitude());
final double long2 = Math.toRadians(other.getLongitude());
final double delta_long = long2 - long1;
final double a = Math.sin(delta_long) * Math.cos(lat2);
final double b = Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(delta_long);
final double bearing = Math.toDegrees(Math.atan2(a, b));
final double bearing_normalized = (bearing + 360) % 360;
return bearing_normalized;
}
//求与该点距离为aDistanceInMeters,aBearingInDegrees的点
public GeoPoint destinationPoint(final double aDistanceInMeters, final double aBearingInDegrees) {
// convert distance to angular distance
final double dist = aDistanceInMeters / RADIUS_EARTH_METERS;
// convert bearing to radians
final double brng = DEG2RAD * aBearingInDegrees;
// get current location in radians
final double lat1 = DEG2RAD * getLatitude();
final double lon1 = DEG2RAD * getLongitude();
final double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) + Math.cos(lat1)
* Math.sin(dist) * Math.cos(brng));
final double lon2 = lon1
+ Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(lat1), Math.cos(dist)
- Math.sin(lat1) * Math.sin(lat2));
final double lat2deg = lat2 / DEG2RAD;
final double lon2deg = lon2 / DEG2RAD;
return new GeoPoint(lat2deg, lon2deg);
}
//两点中心坐标
public static GeoPoint fromCenterBetween(final GeoPoint geoPointA, final GeoPoint geoPointB) {
return new GeoPoint((geoPointA.getLatitude() + geoPointB.getLatitude()) / 2,
(geoPointA.getLongitude() + geoPointB.getLongitude()) / 2);
}
//转换为double字符串
public String toDoubleString() {
return new StringBuilder().append(this.mLatitude).append(",")
.append(this.mLongitude).append(",").append(this.mAltitude).toString();
}
//转换为反向的字符串
public String toInvertedDoubleString() {
return new StringBuilder().append(this.mLongitude).append(",")
.append(this.mLatitude).append(",").append(this.mAltitude).toString();
}
@Deprecated
@Override
public int getLatitudeE6() {
return (int) (this.getLatitude() * 1E6);
}
@Deprecated
@Override
public int getLongitudeE6() {
return (int) (this.getLongitude()* 1E6);
}
}
6. LocationUtils
位置计算工具
public class LocationUtils implements UtilConstants {
private LocationUtils() {
}
//从Gps或网络获取最新的位置
public static Location getLastKnownLocation(final LocationManager pLocationManager) {
if (pLocationManager == null) {
return null;
}
final Location gpsLocation = getLastKnownLocation(pLocationManager, LocationManager.GPS_PROVIDER);
final Location networkLocation = getLastKnownLocation(pLocationManager, LocationManager.NETWORK_PROVIDER);
if (gpsLocation == null) {
return networkLocation;
} else if (networkLocation == null) {
return gpsLocation;
} else {
// both are non-null - use the most recent
if (networkLocation.getTime() > gpsLocation.getTime() + Configuration.getInstance().getGpsWaitTime()) {
return networkLocation;
} else {
return gpsLocation;
}
}
}
private static Location getLastKnownLocation(final LocationManager pLocationManager, final String pProvider) {
try {
if (!pLocationManager.isProviderEnabled(pProvider)) {
return null;
}
} catch (final IllegalArgumentException e) {
return null;
}
return pLocationManager.getLastKnownLocation(pProvider);
}
}
7. SegmentIntersection
计算二维线段交点的类
public class SegmentIntersection {
...
}
8. SegmentClipper
剪切线段工具
public class SegmentClipper {
...
}
9. TileSystem
瓦片系统代理。用于经纬度坐标与瓦片编号系统坐标的转换。
public final class TileSystem {
...
}
10. TileLooper
一个用于给定视口所有地图瓦片的循环。
public abstract class TileLooper {
...
}
11. BoundingBox
有边界的经纬度方框
public class BoundingBox implements Parcelable, Serializable, MapViewConstants {
static final long serialVersionUID = 2L;
protected final double mLatNorth;//框的北边纬度
protected final double mLatSouth;//框的南边纬度
protected final double mLonEast;//框的东边经度
protected final double mLonWest;//框的西边经度
public BoundingBox(final double north, final double east, final double south, final double west) {
this.mLatNorth = north;
this.mLonEast = east;
this.mLatSouth = south;
this.mLonWest = west;
//validate the values
// 30 > 0 OK
// 30 < 0 not ok
if (north > 90.0)
throw new IllegalArgumentException("north must be less than 90");
if (south < -90.0)
throw new IllegalArgumentException("north more than -90");
if (west < -180)
throw new IllegalArgumentException("west must be more than -180");
if (east > 180)
throw new IllegalArgumentException("east must be less than 180");
}
//克隆框
public BoundingBox clone(){
return new BoundingBox(this.mLatNorth, this.mLonEast, this.mLatSouth, this.mLonWest);
}
//获取包含本框以及bb2的经纬度框
public BoundingBox concat(BoundingBox bb2){
return new BoundingBox(
Math.max(this.mLatNorth, bb2.getLatNorth()),
Math.max(this.mLonEast, bb2.getLonEast()),
Math.min(this.mLatSouth, bb2.getLatSouth()),
Math.min(this.mLonWest, bb2.getLonWest()));
}
//获取框的中心经纬度点
@Deprecated
public GeoPoint getCenter() {
return new GeoPoint((this.mLatNorth + this.mLatSouth) / 2.0,
(this.mLonEast + this.mLonWest) / 2.0);
}
public GeoPoint getCenterWithDateLine() {
final double latitude = (mLatNorth + mLatSouth) / 2.0;
double longitude = (mLonEast + mLonWest) / 2.0;
if (mLonEast < mLonWest) {
longitude += TileSystem.MaxLongitude;
}
return new GeoPoint(latitude, longitude);
}
//获取米为单位的对角线距离
public double getDiagonalLengthInMeters() {
return new GeoPoint(this.mLatNorth, this.mLonWest).distanceTo(new GeoPoint(
this.mLatSouth, this.mLonEast));
}
public double getLatNorth() {
return this.mLatNorth;
}
public double getLatSouth() {
return this.mLatSouth;
}
public double getLonEast() {
return this.mLonEast;
}
public double getLonWest() {
return this.mLonWest;
}
//获取纬度差
public double getLatitudeSpan() {
return Math.abs(this.mLatNorth - this.mLatSouth);
}
//获取经度差
public double getLongitudeSpan() {
return Math.abs(this.mLonEast - this.mLonWest);
}
//获取一个经纬度点在框模型中的相对位置,左上点为(0,0),右下角为(1,1)点
public PointF getRelativePositionOfGeoPointInBoundingBoxWithLinearInterpolation(
final double aLatitude, final double aLongitude, final PointF reuse) {
final PointF out = (reuse != null) ? reuse : new PointF();
final float y = (float)((this.mLatNorth - aLatitude) / getLatitudeSpan());
final float x = 1 - (float) ((this.mLonEast - aLongitude) / getLongitudeSpan());
out.set(x, y);
return out;
}
public PointF getRelativePositionOfGeoPointInBoundingBoxWithExactGudermannInterpolation(
final double aLatitude, final double aLongitude, final PointF reuse) {
final PointF out = (reuse != null) ? reuse : new PointF();
final float y = (float) ((gudermannInverse(this.mLatNorth) - gudermannInverse(aLatitude)) / (gudermannInverse(this.mLatNorth) - gudermannInverse(this.mLatSouth)));
final float x = 1 - (float) ((this.mLonEast - aLongitude) / getLongitudeSpan());
out.set(x, y);
return out;
}
//根据相对位置反算经纬度点
public GeoPoint getGeoPointOfRelativePositionWithLinearInterpolation(final float relX,
final float relY) {
double lat = this.mLatNorth - (this.getLatitudeSpan() * relY);
double lon = this.mLonWest + (this.getLongitudeSpan() * relX);
/* Bring into bounds. */
while (lat > 90.5)
lat -= 90.5;
while (lat < -90.5)
lat += 90.5;
/* Bring into bounds. */
while (lon > 180.0)
lon -= 180.0;
while (lon < -180.0)
lon += 180.0;
return new GeoPoint(lat, lon);
}
public GeoPoint getGeoPointOfRelativePositionWithExactGudermannInterpolation(final float relX,
final float relY) {
final double gudNorth = gudermannInverse(this.mLatNorth);
final double gudSouth = gudermannInverse(this.mLatSouth);
double lat = gudermann((gudSouth + (1 - relY) * (gudNorth - gudSouth)));
double lon = this.mLonWest + (this.getLongitudeSpan() * relX);
/* Bring into bounds. */
while (lat > 90.500000)
lat -= 90.500000;
while (lat < -90.500000)
lat += 90.500000;
/* Bring into bounds. */
while (lon > 180.000000)
lon -= 180.000000;
while (lon < -180.000000)
lon += 180.000000;
return new GeoPoint(lat, lon);
}
public BoundingBox increaseByScale(final float pBoundingboxPaddingRelativeScale) {
final GeoPoint pCenter = this.getCenter();
final double mLatSpanPadded_2 = (this.getLatitudeSpan() * pBoundingboxPaddingRelativeScale) / 2.0;
final double mLonSpanPadded_2 = (this.getLongitudeSpan() * pBoundingboxPaddingRelativeScale) / 2.0;
return new BoundingBox(pCenter.getLatitude() + mLatSpanPadded_2,
pCenter.getLongitude() + mLonSpanPadded_2, pCenter.getLatitude()
- mLatSpanPadded_2, pCenter.getLongitude() - mLonSpanPadded_2);
}
@Override
public String toString() {
return new StringBuffer().append("N:").append(this.mLatNorth).append("; E:")
.append(this.mLonEast).append("; S:").append(this.mLatSouth).append("; W:")
.append(this.mLonWest).toString();
}
//将一个点放入一个框模型中
public GeoPoint bringToBoundingBox(final double aLatitude, final double aLongitude) {
return new GeoPoint(Math.max(this.mLatSouth, Math.min(this.mLatNorth, aLatitude)),
Math.max(this.mLonWest, Math.min(this.mLonEast, aLongitude)));
}
//构造一系列点的框模型
public static BoundingBox fromGeoPoints(final List<? extends IGeoPoint> partialPolyLine) {
double minLat = Double.MAX_VALUE;
double minLon = Double.MAX_VALUE;
double maxLat = -Double.MAX_VALUE;
double maxLon = -Double.MAX_VALUE;
for (final IGeoPoint gp : partialPolyLine) {
final double latitude = gp.getLatitude();
final double longitude = gp.getLongitude();
minLat = Math.min(minLat, latitude);
minLon = Math.min(minLon, longitude);
maxLat = Math.max(maxLat, latitude);
maxLon = Math.max(maxLon, longitude);
}
return new BoundingBox(maxLat, maxLon, minLat, minLon);
}
//查看点是否在框中
public boolean contains(final IGeoPoint pGeoPoint) {
return contains(pGeoPoint.getLatitude(), pGeoPoint.getLongitude());
}
public boolean contains(final double aLatitude, final double aLongitude) {
return ((aLatitude < this.mLatNorth) && (aLatitude > this.mLatSouth))
&& ((aLongitude < this.mLonEast) && (aLongitude > this.mLonWest));
}
@Deprecated
public int getLatitudeSpanE6() {
return (int)(getLatitudeSpan() * 1E6);
}
@Deprecated
public int getLongitudeSpanE6() {
return (int)(getLongitudeSpan() * 1E6);
}
...
}