【问题标题】:Get Radius Of Visible Map in Android在Android中获取可见地图的半径
【发布时间】:2015-05-27 04:30:14
【问题描述】:

有没有办法从中间点找到可见地图的半径?

我想从 API 获取靠近地图中心点的位置,而该 API 需要纬度、经度和半径。我能够从中心点获取 lat 和 lng,但找不到获取半径的方法。

谢谢

【问题讨论】:

    标签: android google-maps location


    【解决方案1】:

    对于 Google Maps Android API,您可以通过...获取边界

    从地图参考中,通过getProjection() 获取Projection。而且,

    投影用于在屏幕位置和地理坐标之间进行转换..

    所以从投影中,我们可以使用getVisibleRegion(),并得到地图的VisibleRegion,其中包含一个LatLngBounds,这是一个包含2个LatLng变量的类,一个用于东北边界的一角和西南角的一角。

    所以代码应该是这样的:

            googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition position) {
                    LatLngBounds bounds = googleMap.getProjection().getVisibleRegion().latLngBounds;
                    LatLng northeast = bounds.northeast;
                    LatLng southwest = bounds.southwest;
    
                    Context context = getApplicationContext();
                    CharSequence text = "ne:"+northeast+" sw:"+southwest;
                    int duration = Toast.LENGTH_SHORT;
    
                    Toast toast = Toast.makeText(context, text, duration);
                    toast.show();
                }
            });
    

    =-=-=-=-=-= 编辑:

    可能是我太天真了,只有NE和SW可以解决这个问题,但仅限于用户没有旋转地图或倾斜3D地图的特殊情况。

    因此,您可以直接抓取VisibleRegion,它提供了 4 个变量,farRight、farLeft、nearRight、nearLeft,每个代表该区域的 4 个角。

    然后我们可以计算这 4 个点的区域的宽度和高度,然后选择较小的那个(嗯,有时宽度可能大于高度。)

    而对于计算,我们可以只使用Location.distanceBetween(x1,y1,x2,y2,result) 函数...

    这使得代码如下所示:

                    VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
    
                    LatLng farRight = visibleRegion.farRight;
                    LatLng farLeft = visibleRegion.farLeft;
                    LatLng nearRight = visibleRegion.nearRight;
                    LatLng nearLeft = visibleRegion.nearLeft;
    
                    float[] distanceWidth = new float[2];
                    Location.distanceBetween(
                            (farRight.latitude+nearRight.latitude)/2,
                            (farRight.longitude+nearRight.longitude)/2,
                            (farLeft.latitude+nearLeft.latitude)/2,
                            (farLeft.longitude+nearLeft.longitude)/2,
                            distanceWidth
                            );
    
    
                    float[] distanceHeight = new float[2];
                    Location.distanceBetween(
                            (farRight.latitude+nearRight.latitude)/2,
                            (farRight.longitude+nearRight.longitude)/2,
                            (farLeft.latitude+nearLeft.latitude)/2,
                            (farLeft.longitude+nearLeft.longitude)/2,
                            distanceHeight
                    );
    
                    float distance;
    
                    if (distanceWidth[0]>distanceHeight[0]){
                        distance = distanceWidth[0];
                    } else {
                        distance = distanceHeight[0];
                    }
    

    【讨论】:

    • 我本来想说剩下的只是一道数学题,但我想我太天真了。顺便说一句,距离以米为单位。
    • 您建议的第二种方法确实效果很好。谢谢@kaho
    • @kaho 正如三思而后行代码一次所说的方法很好,但我猜在计算高度时你错误地考虑了最终再次给出宽度的纬度。您应该将经度视为三思而后行已完成
    【解决方案2】:

    非常感谢您的回答 @kaho,它对我帮助很大(即使您以相同的方式计算了 distanceWidth 和 distanceHeight)。

    澄清:

    • farLeft 定义相机左上角的 LatLng 对象。

    • farRight 定义相机右上角的 LatLng 对象。

    • nearLeft 定义相机左下角的 LatLng 对象。

    • nearRight 定义相机右下角的 LatLng 对象。

    已编辑:我不知道为什么我们让一个简单的计算变得有点复杂,可见半径只是可见对角线的一半,仅此而已!

    private double getMapVisibleRadius() {
            VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
    
            float[] diagonalDistance = new float[1];
    
            LatLng farLeft = visibleRegion.farLeft;
            LatLng nearRight = visibleRegion.nearRight;
    
            Location.distanceBetween(
                    farLeft.latitude,
                    farLeft.longitude,
                    nearRight.latitude,
                    nearRight.longitude,
                    diagonalDistance
            );
    
            return diagonalDistance[0] / 2;
        }
    

    我还记录了我的结果以与 @jossef-harush 的结果进行比较,大致如下:

    【讨论】:

    • 里面的数字是多少?弧度?我在这里得到了一些非常大的数字,看起来像米
    • 是的,visibleRadius 的值以米为单位
    • 如何排除不属于可见地图/区域的区域?我说的是不可见的左/右半径曲线。
    • @VVB 你想计算可见矩形面积吗?很简单,从VisibleRegion的4个角点算出来
    • 感谢您的回复。我认为您现有的答案仅以这种方式计算。对吗?
    【解决方案3】:

    整个区域,甚至角落!

    我没有看到其他答案覆盖整个地图区域;

    见下图,为了测试它,我画了一个圆形叠加层来查看计算半径的边界,它没有覆盖整个地图区域。

    我的修改很简单,我用Pythagorean theorem找到合适的半径来包含地图“矩形”。



    private double getMapVisibleRadius() {
        VisibleRegion visibleRegion = googleMap.getProjection().getVisibleRegion();
    
        float[] distanceWidth = new float[1];
        float[] distanceHeight = new float[1];
    
        LatLng farRight = visibleRegion.farRight;
        LatLng farLeft = visibleRegion.farLeft;
        LatLng nearRight = visibleRegion.nearRight;
        LatLng nearLeft = visibleRegion.nearLeft;
    
        Location.distanceBetween(
                (farLeft.latitude + nearLeft.latitude) / 2,
                farLeft.longitude,
                (farRight.latitude + nearRight.latitude) / 2,
                farRight.longitude,
                distanceWidth
        );
    
        Location.distanceBetween(
                farRight.latitude,
                (farRight.longitude + farLeft.longitude) / 2,
                nearRight.latitude,
                (nearRight.longitude + nearLeft.longitude) / 2,
                distanceHeight
        );
    
        double radiusInMeters = Math.sqrt(Math.pow(distanceWidth[0], 2) + Math.pow(distanceHeight[0], 2)) / 2;
        return radiusInMeters;
    }
    

    【讨论】:

    • 谢谢!我发现我的答案不正确。但我也找到了更简单的方法来计算可见半径。我们已经有了坐标值,所以我们不需要应用 Pythagorean 来计算宽度和高度的距离 2 次,您可以查看我更新的答案
    • 如何排除不属于可见地图/区域的区域?我说的是不可见的左/右半径曲线。
    • VVB 圆的一个事实用例是使用 geo latlong + radius 仅从您的数据库中过滤相关数据。可以根据视口的矩形边界框手动过滤掉视口外的结果
    【解决方案4】:

    对于 Kotlin 用户,请从 setOnCameraIdleListener 调用此函数

        private fun getMapVisibleRadius(): Double {
        val visibleRegion: VisibleRegion = mMap.projection.visibleRegion
    
        val distanceWidth = FloatArray(1)
        val distanceHeight = FloatArray(1)
    
        val farRight: LatLng = visibleRegion.farRight
        val farLeft: LatLng = visibleRegion.farLeft
        val nearRight: LatLng = visibleRegion.nearRight
        val nearLeft: LatLng = visibleRegion.nearLeft
    
        Location.distanceBetween((farLeft.latitude + nearLeft.latitude) / 2, farLeft.longitude, (farRight.latitude + nearRight.latitude) / 2, farRight.longitude, distanceWidth)
    
        Location.distanceBetween(farRight.latitude,
                (farRight.longitude + farLeft.longitude) / 2, nearRight.latitude, (nearRight.longitude + nearLeft.longitude) / 2, distanceHeight)
    
        val radiusInMeters = Math.sqrt((Math.pow(distanceWidth.get(0).toString().toDouble(), 2.0))
                + Math.pow(distanceHeight.get(0).toString().toDouble(), 2.0)) / 2
        return radiusInMeters
    }
    

    【讨论】:

      【解决方案5】:

      编辑:以下答案适用于 Google Maps JavaScript API v3
      =-=-=-=-=-=-=

      我认为答案是:是的,你可以。

      根据documentation,您可以通过computeDistanceBetween(LatLngFrom, LatLngTo)计算两点之间的距离

      也可以通过getBounds()方法获取地图的边界,在google.maps.Map class中。

      【讨论】:

      • 感谢您的回复,但是这些方法和这些链接不是指v3吗?哪个现在仅适用于 javascript?
      猜你喜欢
      • 1970-01-01
      • 2011-04-01
      • 2017-10-09
      • 1970-01-01
      • 2016-09-04
      • 1970-01-01
      • 2011-10-15
      • 1970-01-01
      • 2012-02-22
      相关资源
      最近更新 更多