Fórmulas de projeção Mercator comum para o Google Maps que não estão funcionando corretamente

StackOverflow https://stackoverflow.com/questions/2656580

Pergunta

Estou construindo um servidor de sobreposição de ladrilhos para o Google Maps em C#e encontrei alguns exemplos de código diferentes para calcular y a partir da latitude. Depois de fazê -los trabalhar em geral, comecei a notar certos casos em que as sobreposições não estavam alinhando corretamente. Para testar isso, fiz um chicote de teste para comparar a conversão Mercator Lattoy do Google Map com as fórmulas que encontrei online. Como você pode ver abaixo, eles não correspondem em certos casos.

Caso 1

Zoom: O problema é mais evidente quando diminuiu o zoom. De perto, o problema é pouco visível.

Caso #2

Proximidade de pontos aos limites superior e inferior da visualização: o problema é pior no meio dos limites de visualização e melhorar as bordas. Este comportamento pode negar o comportamento do caso nº 1

O teste:

Criei uma página do Google Maps para exibir linhas vermelhas usando a conversão de Mercator da API da API do Google Map e sobrepondo isso com uma imagem usando o código de referência para fazer a conversão do Mercator. Essas conversões são representadas como linhas pretas. Compare a diferença.

Os resultados:Equator http://www.kayak411.com/mercator/mercatorcomparison%20-%20equator.png North ampliou http://www.kayak411.com/mercator/mercatorcomparison%20-%20north%20Zoomed%20out.png

Confira as linhas mais elevadas e mais baixas:Exemplo North Top & Bottom http://www.kayak411.com/mercator/mercatorcomparison%20-%20north%20Zoomed%20out%20-%20TopandBottom.png

O problema fica visualmente maior, mas numericamente menor à medida que você aumenta o zoom:TEXTO DE ALT HTTP://www.kayak411.com/mercator/mercatorcomparison%20-%20north%20Zoomed%20midway.png

E quase desaparece em níveis mais próximos de zoom, independentemente da orientação da tela.TEXTO DE ALT HTTP://www.kayak411.com/mercator/mercatorcomparison%20-%20north%20Zoomed%20in.png

O código:

Google Maps Código lateral do cliente:

            var lat = 0;
        for (lat = -80; lat <= 80; lat += 5) {
            map.addOverlay(new GPolyline([new GLatLng(lat, -180), new GLatLng(lat, 0)], "#FF0033", 2));
            map.addOverlay(new GPolyline([new GLatLng(lat, 0), new GLatLng(lat, 180)], "#FF0033", 2));
        }

Código do lado do servidor:

Cortador de ladrilhos: http://mapki.com/wiki/tile_cutter

OpenStreetMap Wiki: http://wiki.openstreetmap.org/wiki/mercator

 protected override void ImageOverlay_ComposeImage(ref Bitmap ZipCodeBitMap)
        {
            Graphics LinesGraphic = Graphics.FromImage(ZipCodeBitMap);

            Int32 MapWidth = Convert.ToInt32(Math.Pow(2, zoom) * 255);

            Point Offset =
                Cartographer.Mercator2.toZoomedPixelCoords(North, West, zoom);

            TrimPoint(ref Offset, MapWidth);

            for (Double lat = -80; lat <= 80; lat += 5)
            {
                Point StartPoint = Cartographer.Mercator2.toZoomedPixelCoords(lat, -179, zoom);
                Point EndPoint = Cartographer.Mercator2.toZoomedPixelCoords(lat, -1, zoom);

                TrimPoint(ref StartPoint, MapWidth);
                TrimPoint(ref EndPoint, MapWidth);

                StartPoint.X = StartPoint.X - Offset.X;
                EndPoint.X = EndPoint.X - Offset.X;

                StartPoint.Y = StartPoint.Y - Offset.Y;
                EndPoint.Y = EndPoint.Y - Offset.Y;


                LinesGraphic.DrawLine(new Pen(Color.Black, 2),
                    StartPoint.X,
                    StartPoint.Y,
                    EndPoint.X,
                    EndPoint.Y);

                LinesGraphic.DrawString(
                    lat.ToString(),
                    new Font("Verdana", 10),
                    new SolidBrush(Color.Black),
                    new Point(
                        Convert.ToInt32((width / 3.0) * 2.0),
                        StartPoint.Y));
            }
        }

        protected void TrimPoint(ref Point point, Int32 MapWidth)
        {
            point.X = Math.Max(point.X, 0);
            point.X = Math.Min(point.X, MapWidth - 1);

            point.Y = Math.Max(point.Y, 0);
            point.Y = Math.Min(point.Y, MapWidth - 1);
        }

Então, alguém já experimentou isso? Ouso perguntar, resolvi isso? Ou simplesmente tem uma melhor implementação C# da conversão de coordenadas do projeto Mercator?

Obrigado!

Foi útil?

Solução

Obrigado a todos por suas sugestões e assistência.

O que eu finalmente descobri é que não é uma fórmula ou problema técnico, acredito que é um problema de metodologia.

Você não pode definir a área de visualização no formato Lat/LNG e espera preenchê -lo com as projeções Mercator apropriadas. É aí que a distorção acontece. Em vez disso, você deve definir a caixa de visualização correta no Mercator e o Projeto Mercator.

Fazendo isso, consegui combinar corretamente o Google Maps.

Outras dicas

Você pode ter que criar vários pontos ao longo da longtidão para que os pontos sejam projetados corretamente ao longo da latitude. Nos seus exemplos, você está realmente projetando apenas dois pontos no início e no final da linha e conectando os dois.

O problema será mais aparente no equador devido à curvatura mais significativa da Terra. Será menor quando ampliado pelo mesmo motivo.

Dê uma olhada em http://code.google.com/apis/maps/documentation/overlays.html#great_circles

Tente criar seu Google Polyines com o parâmetro geodsico para ver se isso faz a diferença. Eu acho que isso adiciona pontos ao longo da linha e os projeta automaticamente:

var lat = 0;
var polyOptions = {geodesic:true};
for (lat = -80; lat <= 80; lat += 5) {
    map.addOverlay(new GPolyline([new GLatLng(lat, -180), new GLatLng(lat, 0)], "#FF0033", 2, polyOptions));
    map.addOverlay(new GPolyline([new GLatLng(lat, 0), new GLatLng(lat, 180)], "#FF0033", 2, polyOptions));
}

Eu tive que ler isso, pois todas as minhas medições de distância estavam erradas no OpenLayers por razões semelhantes: http://geographika.co.uk/watch-to-for-openlayer-distances (mais links/explicações)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top