MKCoordinateRegionMakeWithDistance equivalent in Android

后端 未结 2 670
伪装坚强ぢ
伪装坚强ぢ 2020-12-14 23:40

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

CLLocationCoordinate2D coord = {latitude:37.09024, longitude:-95.712891         


        
相关标签:
2条回答
  • 2020-12-15 00:19

    This code is not production quality. Use Chris suggestion from comments here instead: https://issuetracker.google.com/issues/35823607#comment4


    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.

    You may want to request this feature on gmaps-api-issues.

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

    Usage:

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

    Notes:

    • 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
    0 讨论(0)
  • 2020-12-15 00:32

    While the above answer might work, it does not really look straight forward as the author already mentioned. Here is some code that works for me. Please note the code assumes the earth is a perfect sphere.

    double latspan = (latMeters/111325);
    double longspan = (longMeters/111325)*(1/ Math.cos(Math.toRadians(location.latitude))); 
    
    LatLngBounds bounds = new LatLngBounds(
        new LatLng(location.latitude-latspan, location.longitude-longspan),
        new LatLng(location.latitude+latspan, location.longitude+longspan));
    
    0 讨论(0)
提交回复
热议问题