MKCoordinateRegionMakeWithDistance 在 Android 中的等效项

Posted

技术标签:

【中文标题】MKCoordinateRegionMakeWithDistance 在 Android 中的等效项【英文标题】:MKCoordinateRegionMakeWithDistance equivalent in Android 【发布时间】:2011-09-07 15:43:50 【问题描述】:

我们可以在 iPhone 的地图上设置特定位置的周边区域如下

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 有没有等效的方法?

【问题讨论】:

【参考方案1】:

此代码不是生产质量。在这里使用来自 cmets 的 Chris 建议:https://issuetracker.google.com/issues/35823607#comment4


这个问题最初是针对 Maps API v1 提出的。此答案适用于 v2,但可以轻松更改为 v1,所以...

没有简单的方法。

您可能想request this feature on gmaps-api-issues。

由于等待在 Google 方面实施可能需要几个月的时间,所以我会这样做:

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

注意事项:

此代码尚未经过全面测试,可能不适用于边缘情况 您可能需要调整私有常量以使其执行得更快 您可以删除计算 LatLng south 的第 3 部分,并像处理经度一样:这对于较小的 latDistance 值是准确的(假设您在 100 公里以下看不到差异) 代码很丑,请随意重构

【讨论】:

此代码在某些设备(例如华为 G700)上导致 ANR,此处跟踪日志:hastebin.com/nufokuxebi.avrasm @Nima 此代码不是生产质量。改用 cmets 的 Chris 建议:code.google.com/p/gmaps-api-issues/issues/detail?id=5704 @MaciejGórski 是的,已经这样做了……但是您的代码也很有趣,谢谢。【参考方案2】:

虽然上述答案可能有效,但正如作者已经提到的那样,它并没有真正向前看。这是一些对我有用的代码。请注意,代码假设地球是一个完美的球体。

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

【讨论】:

简单、简洁且足以满足大多数应用程序的需要。谢谢 111325 的数字是什么? 如果这能解释什么是 111325 会更好。

以上是关于MKCoordinateRegionMakeWithDistance 在 Android 中的等效项的主要内容,如果未能解决你的问题,请参考以下文章