14 votos

Cómo calcular el nivel de zoom óptimo para mostrar dos o más puntos en un mapa

Queremos mostrar varios marcadores en un mapa estático y queremos calcular el nivel de zoom óptimo como hace Google Maps. Ya hemos calculado el rectángulo delimitador y el punto central del mapa, pero ahora nos cuesta calcular el nivel de zoom correcto para mostrar todo el rectángulo delimitador. ¿Puede alguien indicarnos la dirección correcta?

7voto

Mattias Puntos 1058

Para obtener el nivel de zoom, necesitarás conocer las dimensiones en píxeles de tu mapa. También tendrás que hacer tus cálculos en coordenadas mercator esféricas.

  1. Convertir latitud, longitud a mercador esférico x, y.
  2. Obtenga la distancia entre sus dos puntos en mercator esférico.
  3. El ecuador tiene unos 40 metros de longitud proyectada y las baldosas tienen 256 píxeles de ancho, por lo que la longitud en píxeles de ese mapa a un nivel de zoom determinado es de unos 256 * distancia/40000000 * 2^zoom . Pruebe con zoom=0, zoom=1, zoom=2 hasta que la distancia sea demasiado larga para las dimensiones en píxeles de su mapa.

5voto

dlinsin Puntos 5863

Este es el código C# que utilizo en Maperitive :

    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 Caja delimitadora en coordenadas long/lat (x=long, y=lat)
  • paddingFactor : se puede utilizar para conseguir el efecto "120%" al que se refiere ThomM. Con un valor de 1,2 se obtendría el 120%.

Tenga en cuenta que en mi caso zoom puede ser un número real. En el caso de los mapas web, se necesita un valor de zoom entero, por lo que se debe utilizar algo como (int)Math.Floor(zoom) para conseguirlo.

Por supuesto, este código sólo se aplica a la proyección Web Mercator.

1voto

blowmage Puntos 2587

Si utiliza OpenLayers, entonces Map.getZoomForExtent calculará el nivel de zoom más alto que pueda caber en toda la extensión del mapa. La página web extent tiene que estar en la proyección del mapa. También puede utilizar un fill_factor para evitar la visualización de puntos en el borde del mapa, y max_zoom para limitar el zoom posible:

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

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X