如何计算最佳缩放级别以在地图上显示两个或多个点


12

我们想要在静态地图上显示几个标记,并希望像Google Maps一样计算最佳缩放级别。我们已经计算了地图的边界矩形和中心点,但是现在我们很难计算正确的缩放级别以显示整个边界矩形。有人可以指出我们正确的方向吗?


它不是很复杂,但是为什么不将MBR乘以120%并缩放到该值呢?还有什么取决于您对“最优”的定义,不是吗?
ThomM '02

+1符合ThomM的想法。这正是ArcGIS所做的。
拉吉·亚瑟·伯姆

1
抱歉,这是什么MBR?
罗德里戈

Answers:


5

要获得缩放级别,您需要知道地图的像素尺寸。您还需要在球形墨卡托坐标中进行数学运算。

  1. 将经度和纬度转换为球形墨卡托x,y。
  2. 在球形墨卡托中获得两点之间的距离。
  3. 赤道投影的长度约为40m米,图块的宽度为256个像素,因此在给定的缩放级别下,该地图的像素长度约为256 *距离/ 40000000 * 2 ^ zoom。尝试zoom = 0,zoom = 1,zoom = 2,直到距离对于地图的像素尺寸而言太长为止。

1
希望我能远程理解您的实际要求。= \
Michal Migurski

在寻找此答案的同时发现了这个问题,谢谢。
BenjaminGolder

@MichalMigurski您能解释一下如何计算球形墨卡托两点之间的距离吗?特别是x坐标...我被卡住了,谢谢。
otmezger 2013年

5

这是我在Maperitive中使用的C#代码:

    public void ZoomToArea (Bounds2 mapArea, float paddingFactor)
    {
        double ry1 = Math.Log((Math.Sin(GeometryUtils.Deg2Rad(mapArea.MinY)) + 1) 
            / Math.Cos(GeometryUtils.Deg2Rad(mapArea.MinY)));
        double ry2 = Math.Log((Math.Sin(GeometryUtils.Deg2Rad(mapArea.MaxY)) + 1) 
            / Math.Cos(GeometryUtils.Deg2Rad(mapArea.MaxY)));
        double ryc = (ry1 + ry2) / 2;
        double centerY = GeometryUtils.Rad2Deg(Math.Atan(Math.Sinh(ryc)));

        double resolutionHorizontal = mapArea.DeltaX / Viewport.Width;

        double vy0 = Math.Log(Math.Tan(Math.PI*(0.25 + centerY/360)));
        double vy1 = Math.Log(Math.Tan(Math.PI*(0.25 + mapArea.MaxY/360)));
        double viewHeightHalf = Viewport.Height/2.0f;
        double zoomFactorPowered = viewHeightHalf
            / (40.7436654315252*(vy1 - vy0));
        double resolutionVertical = 360.0 / (zoomFactorPowered * 256);

        double resolution = Math.Max(resolutionHorizontal, resolutionVertical) 
            * paddingFactor;
        double zoom = Math.Log(360 / (resolution * 256), 2);
        double lon = mapArea.Center.X;
        double lat = centerY;

        CenterMapOnPoint(new PointD2(lon, lat), zoom);
    }
  • mapArea:长/纬度坐标中的边界框(x = long,y = lat)
  • paddingFactor:可以用来获得ThomM所指的“ 120%”效果。值为1.2将使您获得120%的收益。

请注意,在我的情况下zoom可以是实数。对于Web地图,您需要一个整数缩放值,因此您应该使用类似的方法(int)Math.Floor(zoom)来获取它。

当然,此代码仅适用于Web Mercator投影。


1
谢谢你 CenterMapOnPoint的代码是否可用?
mcintyre321 2014年

完善!我已经用它来计算OsmDroid SDK中BoundingBox的缩放,并且可以正常工作:)
Billda

在哪里可以找到这些库?我找不到GeometryUtils或Bounds2组件。我需要从maperitive下载一些东西吗?我在那里只看到一个应用。
Dowlers '19

@Dowlers GeometryUtils仅在这里用于将度数转换为弧度并返回,这是一个简单的数学公式。Bounds2基本上只是一个矩形结构。与直接复制可粘贴的内容相比,此代码更多是作为伪代码提供的。
伊戈尔·布雷耶克

1
这真棒@IgorBrejc-非常感谢!我将其转换为python,以防其他人正在编写python代码:gist.github.com/mappingvermont/d534539fa3ebe4a1e242644e528bf7b9
Charlie Hofmann

1

如果您使用的是OpenLayers,Map.getZoomForExtent则将计算可适合地图上整个范围的最高缩放级别。该extent需求是在地图的投影。您还可以使用fill_factor来避免在地图边缘上显示点,并max_zoom限制可能的缩放比例:

extent = extent.scale(1/fill_ratio);
var zoom = Math.min(map.getZoomForExtent(map_extent), max_zoom);
map.setCenter(extent.getCenterLonLat(), zoom);

这不能解决我的问题,但是导致我找到了Leaflet的fitBounds方法,从而节省了我的时间。
SamuelDev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.