2010-04-16 15 views
6

Sto creando un server di sovrapposizione di tile per le mappe di Google in C# e ho trovato alcuni esempi di codice diversi per il calcolo di Y da Latitude. Dopo averli fatti lavorare in generale, ho iniziato a notare alcuni casi in cui le sovrapposizioni non si allineavano correttamente. Per verificare ciò, ho creato un cablaggio di prova per confrontare la conversione di Mercator LatToY di Google Map con le formule che ho trovato online. Come puoi vedere di seguito, in alcuni casi non corrispondono.Le formule comuni di Mercator Projection per Google Maps non funzionano correttamente

Caso # 1

ingrandito: Il problema è più evidente quando zoom out. Da vicino, il problema è a malapena visibile.

Caso # 2

Point Vicinanza Top & Basso limiti di visualizzazione: Il problema è peggiore nel mezzo dei limiti di visualizzazione, e migliora verso i bordi. Questo comportamento può negare il comportamento di Case # 1

Il Test:

ho creato una pagina di google maps per linee rosse visualizzazione utilizzando Google Map di conversione incorporata in Mercator, API e sovrapponi questo con un'immagine usando il codice di riferimento per fare la conversione di Mercator . Queste conversioni sono rappresentate come linee nere. Confronta la differenza.

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

Scopri le più in alto e più in basso linee: North Top & Bottom Example http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Out%20-%20TopAndBottom.png

Il problema diventa visivamente più grande, ma numericamente inferiore, come si ingrandisce: alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20Midway.png

E tutto scompare a livelli di zoom più ravvicinati, indipendentemente dallo scre orientamento. alt text http://www.kayak411.com/Mercator/MercatorComparison%20-%20North%20Zoomed%20In.png

Il Codice:

Google Maps Codice Cliente laterale:

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

codice lato server:

Cutter Tile: 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); 
     } 

Quindi, Chiunque abbia mai sperimentato questo? Posso chiedere, ho risolto questo? O semplicemente una migliore implementazione in C# della conversione delle coordinate del Progetto Mercator?

Grazie!

+0

si dovrebbe verificare SharpMap e proj.net, sono su CodePlex –

+0

sguardo gdal.org – dassouki

+0

@ Muad'Dib Grazie per il suggerimento. Ho preso le cose di Proj.net, ma la loro formula di proiezione non tiene conto del fattore di zoom, e non riesco a capire come applicarlo. (http://projnet.codeplex.com/Thread/View.aspx?ThreadId=77458) Sembra inoltre che SharpMap utilizzi Proj.net come motore di proiezione, quindi probabilmente non sarà di grande aiuto. –

risposta

1

Grazie a tutti per i suggerimenti & assistenza.

Quello che ho scoperto è che non è una formula o un problema tecnico, credo che sia un problema di metodologia.

Non è possibile definire l'area di visualizzazione in formato Lat/Lng e aspettarsi di popolarlo con le proiezioni di Mercator appropriate. Ecco dove avviene la distorsione. Invece, devi definire la casella di visualizzazione corretta in Mercator e proiettare Mercator.

In questo modo sono riuscito a far corrispondere correttamente le mappe di Google.

0

Potrebbe essere necessario creare più punti lungo la longitudine in modo che i punti vengano proiettati correttamente lungo la latitudine. Nei tuoi esempi stai solo proiettando due punti all'inizio e alla fine della linea e collegandoli.

Il problema sarà più evidente all'equatore a causa della curvatura più significativa della terra. Sarà inferiore se ingrandito per lo stesso motivo.

Dai un'occhiata alla http://code.google.com/apis/maps/documentation/overlays.html#Great_Circles

provare a creare i tuoi polilinee di Google con il parametro geodsic per vedere se questo fa la differenza. Credo che questo aggiunge punti lungo la linea e li proietta 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)); 
} 

Ho dovuto leggere in questo come tutti i miei le misure di distanza erano sbagliate in OpenLayers per ragioni analoghe: http://geographika.co.uk/watch-out-for-openlayer-distances (more links/spiegazioni)