osmdroid API解读(十)

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);
     }
        ...

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OSMDroid 是一个开源的 Android 地图库,它允许开发者在 Android 应用程序中嵌入 OpenStreetMap 数据和地图功能。与原生 Google Maps API 不同,OSMDroid 是基于轻量级的 OSM 数据,这意味着它可以提供更好的离线地图支持,并且对隐私更加友好。 防止内存泄露(Memory Leaks)是 Android 开发中非常重要的一环,特别是在处理地图相关组件时,因为地图数据加载和绘制可能会占用大量内存。以下是一些避免 OSMDroid 防止内存泄露的方法: 1. **及时释放资源**:确保每次不再使用地图视图(MapView)、图层(Overlay)或数据源(TileProvider)时,调用相应的 `dispose()` 或 `removeAllOverlays()` 方法释放它们。 2. **使用弱引用**:对于持有地图对象的引用,可以考虑使用 WeakReference,这样即使其他强引用消失,弱引用也不会阻止垃圾回收。 3. **监听生命周期**:地图视图的 `OnDestroy()` 或 `onSaveInstanceState()` 方法中,记得清除地图相关的回调和监听器,以防止内存泄漏。 4. **批处理操作**:尽量减少在主线程执行耗时的操作,如绘制大图层或加载大量数据,可以使用异步任务或者 `AsyncTask` 来处理。 5. **使用 LruCache**:对于频繁访问但占用空间较大的地图数据,可以使用 LruCache 来缓存,当内存不足时自动清理最久未使用的数据。 6. **跟踪内存使用**:利用 Android 的内存分析工具(如 Android Studio 的 Memory Profiler 或第三方库如 LeakCanary)定期检查应用内存状况,找出可能的泄漏点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值