MKCoordinateRegionMakeWithDistance相当于机器人机器人、MKCoordinateRegionMakeWithDistance

2023-09-04 05:12:10 作者:还是一人

我们可以按照下面的iPhone设置为特定位置周边地区的地图

We can set the surrounding area for particular location on map in iPhone as following

CLLocationCoordinate2D coord = {latitude:37.09024, longitude:-95.712891};
CLLocationDistance latitudinalMeters;
latitudinalMeters =NoOfMiles * 1609.344;
CLLocationDistance longitudinalMeters;
longitudinalMeters = NoOfMiles * 1609.344;
mapViewHome.region = MKCoordinateRegionMakeWithDistance(coord, latitudinalMeters, longitudinalMeters); 

是否有Android的任何等同方法?

Is there any equivalent method for Android?

推荐答案

这个问题最初是问地图API V1。这个答案是V2,但可以很容易地变更为V1,所以......

This question was originally asked for Maps API v1. This answer is for v2, but can be easily changed to v1, so...

没有简单的方法来做到这一点。

No easy way to do it.

您可能需要要求这在功能GMaps实现-API的问题。

由于等待这是在谷歌方面实现可能需要数月,所以这是我会做什么:

As waiting for this to be implemented on Google side can take several months, so this is what I would do:

private static final double ASSUMED_INIT_LATLNG_DIFF = 1.0;
private static final float ACCURACY = 0.01f;

public static LatLngBounds boundsWithCenterAndLatLngDistance(LatLng center, float latDistanceInMeters, float lngDistanceInMeters) {
    latDistanceInMeters /= 2;
    lngDistanceInMeters /= 2;
    LatLngBounds.Builder builder = LatLngBounds.builder();
    float[] distance = new float[1];
    {
        boolean foundMax = false;
        double foundMinLngDiff = 0;
        double assumedLngDiff = ASSUMED_INIT_LATLNG_DIFF;
        do {
            Location.distanceBetween(center.latitude, center.longitude, center.latitude, center.longitude + assumedLngDiff, distance);
            float distanceDiff = distance[0] - lngDistanceInMeters;
            if (distanceDiff < 0) {
                if (!foundMax) {
                    foundMinLngDiff = assumedLngDiff;
                    assumedLngDiff *= 2;
                } else {
                    double tmp = assumedLngDiff;
                    assumedLngDiff += (assumedLngDiff - foundMinLngDiff) / 2;
                    foundMinLngDiff = tmp;
                }
            } else {
                assumedLngDiff -= (assumedLngDiff - foundMinLngDiff) / 2;
                foundMax = true;
            }
        } while (Math.abs(distance[0] - lngDistanceInMeters) > lngDistanceInMeters * ACCURACY);
        LatLng east = new LatLng(center.latitude, center.longitude + assumedLngDiff);
        builder.include(east);
        LatLng west = new LatLng(center.latitude, center.longitude - assumedLngDiff);
        builder.include(west);
    }
    {
        boolean foundMax = false;
        double foundMinLatDiff = 0;
        double assumedLatDiffNorth = ASSUMED_INIT_LATLNG_DIFF;
        do {
            Location.distanceBetween(center.latitude, center.longitude, center.latitude + assumedLatDiffNorth, center.longitude, distance);
            float distanceDiff = distance[0] - latDistanceInMeters;
            if (distanceDiff < 0) {
                if (!foundMax) {
                    foundMinLatDiff = assumedLatDiffNorth;
                    assumedLatDiffNorth *= 2;
                } else {
                    double tmp = assumedLatDiffNorth;
                    assumedLatDiffNorth += (assumedLatDiffNorth - foundMinLatDiff) / 2;
                    foundMinLatDiff = tmp;
                }
            } else {
                assumedLatDiffNorth -= (assumedLatDiffNorth - foundMinLatDiff) / 2;
                foundMax = true;
            }
        } while (Math.abs(distance[0] - latDistanceInMeters) > latDistanceInMeters * ACCURACY);
        LatLng north = new LatLng(center.latitude + assumedLatDiffNorth, center.longitude);
        builder.include(north);
    }
    {
        boolean foundMax = false;
        double foundMinLatDiff = 0;
        double assumedLatDiffSouth = ASSUMED_INIT_LATLNG_DIFF;
        do {
            Location.distanceBetween(center.latitude, center.longitude, center.latitude - assumedLatDiffSouth, center.longitude, distance);
            float distanceDiff = distance[0] - latDistanceInMeters;
            if (distanceDiff < 0) {
                if (!foundMax) {
                    foundMinLatDiff = assumedLatDiffSouth;
                    assumedLatDiffSouth *= 2;
                } else {
                    double tmp = assumedLatDiffSouth;
                    assumedLatDiffSouth += (assumedLatDiffSouth - foundMinLatDiff) / 2;
                    foundMinLatDiff = tmp;
                }
            } else {
                assumedLatDiffSouth -= (assumedLatDiffSouth - foundMinLatDiff) / 2;
                foundMax = true;
            }
        } while (Math.abs(distance[0] - latDistanceInMeters) > latDistanceInMeters * ACCURACY);
        LatLng south = new LatLng(center.latitude - assumedLatDiffSouth, center.longitude);
        builder.include(south);
    }
    return builder.build();
}

用法:

LatLngBounds bounds = AndroidMapsExtensionsUtils.boundsWithCenterAndLatLngDistance(new LatLng(51.0, 19.0), 1000, 2000);
map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));

注:

在此code还没有经过全面测试,可以用于边缘的情况下无法正常工作 您可能需要调整私人常数有它执行得更快 您可以删除其中经纬度南计算第三部分,做它像经度:这将是准确latDistance小值(猜你不会看到有差别在100公里) code是丑陋的,可以随意重构 this code has not been fully tested, may not work for edge cases you may want to adjust private constants to have it execute faster you may remove 3rd part where LatLng south is calculated and do it like for longitudes: this will be accurate for small values of latDistance (guessing you will not see a difference under 100km) code is ugly, so feel free to refactor
 
精彩推荐