繁体   English   中英

根据位置准确性确定Google地图的合理缩放级别

[英]Determine a reasonable zoom level for Google Maps given location accuracy

我正在尝试将Google地图集中到用户位置,同时考虑到该位置的准确性,提供合理的缩放级别。 任何人都可以描述我应该如何计算它? 涉及哪些变量,您是如何实现这一目标的?

您正在寻找的是根据位置精度计算缩放级别的公式。

我设法得出这个公式(在我的测试中)工作得很好。

式

这可以简化(可能不是这样):

简化/疤痕配方

这个可怕的东西就是你想要的。

EquatorLength是40,075,004米。 可以通过将精度圆的直径乘以设备屏幕的长度(以像素为单位)来计算Meters/Pixel

这是我用来测试这个公式的示例程序:

GoogleMap mMap;

@Override
protected void onStart() {
    super.onStart();

    mMap = ((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();

    // Enable user's location layer
    mMap.setMyLocationEnabled(true);

    mMap.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
        @Override
        public void onMyLocationChange(Location location) {
            // Location lat-lng
            LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());

            // Location accuracy diameter (in meters)
            float accuracy = location.getAccuracy() * 2;

            // Screen measurements
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            // Use min(width, height) (to properly fit the screen
            int screenSize = Math.min(metrics.widthPixels, metrics.heightPixels);

            // Equators length
            long equator = 40075004;

            // The meters per pixel required to show the whole area the user might be located in
            double requiredMpp = accuracy/screenSize;

            // Calculate the zoom level
            double zoomLevel = ((Math.log(equator / (256 * requiredMpp))) / Math.log(2)) + 1;

            Log.e(TAG, String.format("Accuracy: %f. Screen Width: %d, Height: %d",
                    accuracy, metrics.widthPixels, metrics.heightPixels));
            Log.e(TAG, String.format("Required M/Px: %f Zoom Level: %f Approx Zoom Level: %d",
                    requiredMpp, zoomLevel, calculateZoomLevel(screenSize, accuracy)));

            // Center to user's position
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, (float) zoomLevel));

            // Prevent the camera centering on the user again
            mMap.setOnMyLocationChangeListener(null);
        }
    });

}

private int calculateZoomLevel(int screenWidth, float accuracy) {
    double equatorLength = 40075004; // in meters
    double metersPerPixel = equatorLength / 256;
    int zoomLevel = 1;
    while ((metersPerPixel * (double) screenWidth) > accuracy) {
        metersPerPixel /= 2;
        zoomLevel++;
    }

    return zoomLevel;
}

几点注意事项:

  • 这个答案基于并实现它以检查生成的值
  • 准确度是用户位置的半径,根据文档,它可以高达68%的正确率。

任何更正都非常受欢迎。

谢谢@Simas! 鉴于CLLocation的准确性,我拿起你的算法对GMSMapView进行扩展以计算理想的zoomLevel。

我不得不进行调整以考虑使用Retina显示器的设备,因为每个像素与屏幕上的1个点不完全相同:

extension GMSMapView {

    func getIdealZoomLevel(usingLocation location:CLLocation)->Float {

        let retinaScale = Double(UIScreen.mainScreen().scale)

        let equatorLength : Double = 40075004 // in meters
        var metersPerPixel = equatorLength / 256
        let accuracy = location.horizontalAccuracy
        // I used height because I'm on landscape, but moving forward I'll have to get the Min of the width and height.
        // I also took only 75% of the height to give it some margin
        let screenWidth : Double = Double( self.frame.size.height) * 0.75

        var display = metersPerPixel * (screenWidth / retinaScale)

        var zoomLevel : Float = 0.0

        while (display > accuracy) {
            metersPerPixel /= 2
            display = metersPerPixel * (screenWidth / retinaScale)
            zoomLevel += 1
        }

        return zoomLevel
    }
}

这是我正在进行的Swift项目,现在,我能够在给定的CLLocation中显示一个包围半径的良好邻近度。

希望这可以帮助。

如果你正在寻找一些简单的东西:

var zoom = Math.min(20, Math.max(1, Math.log2(591657550/accuracy)-2));

调整-2以获得所需的缩放。

查看此答案以获得准确对应缩放的图表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM