2010-04-16 6 views
6

Estoy construyendo un servidor de superposición de mosaicos para mapas de Google en C#, y he encontrado algunos ejemplos de códigos diferentes para calcular Y desde Latitude. Después de hacerlos trabajar en general, comencé a notar ciertos casos donde las superposiciones no se alineaban correctamente. Para probar esto, hice un arnés de prueba para comparar la conversión de Mercator LatToY de Google Map con las fórmulas que encontré en línea. Como puede ver a continuación, no coinciden en ciertos casos.Las fórmulas comunes de proyección de Mercator para Google Maps no funcionan correctamente

Caso # 1

alejaste: El problema es más evidente cuando está reducida. De cerca, el problema es apenas visible.

Caso # 2

punto de proximidad hacia arriba & Parte inferior de límites de visualización: El problema es peor en medio de los límites de visualización, y pone mejor hacia los bordes. Este comportamiento se puede negar el comportamiento de Caso # 1

La prueba:

he creado una página de mapas de Google para líneas rojas de visualización utilizando el Google Map incorporado en la conversión de Mercator, API y superponga esto con una imagen usando el código de referencia para hacer la conversión de Mercator . Estas conversiones son representadas como líneas negras. Comparar la diferencia.

Los Resultados: Equator http://www.kayak411.com/Mercator/MercatorComparison%20-%20Equator.png North Zoomed Out http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out.png

Mira la-la mayoría y de abajo mayoría de las líneas: North Top & Bottom Example http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out%20-%20TopAndBottom.png

El problema se vuelve visualmente más grande, pero numéricamente menor medida que se acerca: alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Midway.png

Y todo desaparece a niveles de zoom más cercanos, independientemente de scre en orientación. alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20In.png

El Código:

Google Maps código del lado del 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 del lado del servidor:

cortador de azulejo: 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); 
     } 

Por lo tanto, cualquier persona que he experimentado esto? Me atrevo a preguntar, ¿resolvió esto? ¿O simplemente tener una mejor implementación de C# de la conversión de coordenadas del Proyecto Mercator?

Gracias!

+0

que debe salir SharpMap y proj.net, que están en –

+0

mirada en CodePlex gdal.org – dassouki

+0

@ Muad'Dib Gracias por la sugerencia. Agarré las cosas de Proj.net, pero su fórmula de proyección no tiene en cuenta el factor de zoom, y no puedo encontrar la manera de aplicarlo. (http://projnet.codeplex.com/Thread/View.aspx?ThreadId=77458) También parece que SharpMap usa Proj.net como su motor de proyección, por lo que probablemente no sea de mucha ayuda. –

Respuesta

1

Gracias a todos por sus sugerencias & asistencia.

Lo que finalmente descubrí es que no es una fórmula o problema técnico, creo que es un problema de metodología.

No puede definir el área de visualización en formato Lat/Lng, y espera llenarlo con las proyecciones de Mercator correspondientes. Ahí es donde ocurre la distorsión. En su lugar, debe definir el cuadro de visualización correcto en Mercator y proyectar Mercator.

Al hacer eso, pude hacer coincidir correctamente con los mapas de Google.

0

Puede que tenga que crear varios puntos a lo largo de la longitud para que los puntos se proyecten correlatamente a lo largo de la latitud. En sus ejemplos, solo está proyectando dos puntos al principio y al final de la línea y conectando los dos.

El problema será más evidente en el ecuador debido a la curvatura más significativa de la tierra. Será menos cuando se acerca por la misma razón.

Tenga una mirada en http://code.google.com/apis/maps/documentation/overlays.html#Great_Circles

intente crear polilíneas de Google con el parámetro geodsic para ver si esto hace la diferencia. Creo que esto añade puntos a lo largo de la línea y los proyecta de forma automática:

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)); 
} 

tuve que leer en esto como todos mis mediciones de distancia estaban mal en OpenLayers por razones similares: http://geographika.co.uk/watch-out-for-openlayer-distances (más enlaces/explicaciones)

Cuestiones relacionadas