Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
899 views
in Technique[技术] by (71.8m points)

google maps - MKCoordinateRegionMakeWithDistance equivalent in Android

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

Is there any equivalent method for Android?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...