Come posso ottenere la latitudine, la longitudine da x, y su una mappa di Mercatore (JPEG)?

Ho una proiezione di Mercatore mappa come JPEG e vorrei sapere come relazionarsi con un dato x, y coordinate di latitudine e longitudine. Ho guardato il Gudermannian funzione ma, onestamente, non riesco a capire come prendere quella funzione e applicare. Cioè, che cosa si aspetta? L’implementazione che ho trovato (JavaScript) sembra avere una vasta gamma tra-PI e PI, ma qual è la correlazione tra il valore y in pixel e di che portata?

Inoltre, ho trovato questa funzione che prende una latitudine e restituisce la tessera per Google Maps, che si avvale anche di Mercatore. Sembrerebbe che se sapessi come inverso di questa funzione, mi piacerebbe essere abbastanza vicino ad avere la mia risposta.

/*<summary>Get the vertical tile number from a latitude
using Mercator projection formula</summary>*/

    private int getMercatorLatitude(double lati)
    {
        double maxlat = Math.PI;

        double lat = lati;

        if (lat > 90) lat = lat - 180;
        if (lat < -90) lat = lat + 180;

        //conversion degre=>radians
        double phi = Math.PI * lat /180;

        double res;
        //double temp = Math.Tan(Math.PI /4 - phi /2);
        //res = Math.Log(temp);
        res = 0.5 * Math.Log((1 + Math.Sin(phi)) /(1 - Math.Sin(phi)));
        double maxTileY = Math.Pow(2, zoom);
        int result = (int)(((1 - res /maxlat) /2) * (maxTileY));

        return (result);
    }
  • Se ricordo correttamente, google utilizza una proiezione equirettangolare, non mercator.
  • Sia Virtual Earth e Google Mercator.
  • Inoltre, l’utile massima latitudine quando si utilizza Mercator non è +-90 gradi – è di circa +-85.05112878 gradi. Il valore è infinito ai poli, quindi devi per coronare il tutto, e di ignorare i poli.
  • Davvero completo il problema, è necessario conoscere il livello di zoom quando si lavora con piastrelle.
  • Io sono un po ‘ poco chiaro su questo. Vuoi fare (x, y) -> (lat, long) o (lat, long) -> (x,y)?

 

5 Replies
  1. 8

    Qui è un po ‘ di codice per te… fammi sapere se hai bisogno di ulteriori spiegazioni.

        ///<summary>
        ///Calculates the Y-value (inverse Gudermannian function) for a latitude. 
        ///<para><see cref="http://en.wikipedia.org/wiki/Gudermannian_function"/></para>
        ///</summary>
        ///<param name="latitude">The latitude in degrees to use for calculating the Y-value.</param>
        ///<returns>The Y-value for the given latitude.</returns>
        public static double GudermannianInv(double latitude)
        {
            double sign = Math.Sign(latitude);
            double sin = Math.Sin(latitude * RADIANS_PER_DEGREE * sign);
            return sign * (Math.Log((1.0 + sin) /(1.0 - sin)) /2.0);
        }
    
        ///<summary>
        ///Returns the Latitude in degrees for a given Y.
        ///</summary>
        ///<param name="y">Y is in the range of +PI to -PI.</param>
        ///<returns>Latitude in degrees.</returns>
        public static double Gudermannian(double y)
        {
            return Math.Atan(Math.Sinh(y)) * DEGREES_PER_RADIAN;
        }
    
    • Grazie! Di provare questo fuori proprio ora.
    • Quindi, se ho un immagine della mappa di mercatore 1588 pixel di altezza, e voglio sapere la latitudine dove y = 677, vorrei capire 677 in termini di +PI di PI e chiamata Gudermannian(y_in_terms_of_pi)? Mi rendo conto che è sbagliato, ma si può vedere dove mi sono bloccato mentalmente qui …
    • Per esempio, su un 1588 pixel di altezza mercator mappa, 30.0 N è 615 pixel dall’alto. Ma se esprimo 615 in termini di un intervallo lineare da PI (0)- PI (1588), mi 615 -> 0.70824318. E chiamando il sopra Gudermannian(0.70824318) produce 37.5587, non 30.0.
    • Ovviamente il problema è il ‘esprimere 615 in termini di una gamma lineare’. Allora, come faccio a fare questo?
    • In sostanza, è necessario fare qualcosa di simile a questo: lat = Gudermannian(Ymax – ((y / Altezza) * (Ymax – Ymin))); dove e Ymin Ymax sono dato da prendere l’inverso Gudermannian di +-85.05112878 (o qualunque sia il limiti max e min latitudini dell’immagine) l’Altezza e le dimensioni della vostra immagine. Se siete di affiancamento, questo funziona anche come lungo come si sostituisce il Ymin Ymax e con la tegola limiti di Altezza e con la tegola dimensione. Che senso ha?
    • def convert_y_to_lat(y): Ymax = gudermannian_inv(gudermannian(la matematica.pi)); Ymin = gudermannian_inv(gudermannian(la matematica.pi)) * -1; Altezza = 1588; lat = gudermannian(Ymax – ((y / Altezza) * (Ymax – Ymin))); return lat; convert_y_to_lat(615) torna 4.42964421829. Mi aspettavo di tornare 30.0. 🙁
    • Non è possibile utilizzare PI. Che è solo il limite che non si sarà mai raggiungere. Invece, utilizzare il valore di 85.05112878 gradi (convertito in radianti).
    • Ho 37.5587 quando y = 615. Per i 30 gradi, y dovrebbe essere 655.17. Che cosa ti rende così sicuro che 615 == 30 gradi?
    • Sul mio mercator tutto il mondo piastrelle riproporzionato al 1588 di altezza, in pixel 615 (dall’alto) attraversa la Spagna da qualche parte vicino a Cartagena e la Sicilia in provincia di Catania, che è a circa 37 gradi, a 32 minuti a Nord, quindi non credo che 30.0 è corretto.

  2. 2

    Erich Mirabal risposta era del tutto corretta (se non del tutto completa).

    Ho appena testato utilizzando un ‘teorico 256×256 Mercator tile’ (Google singola piastrella versione di una mappa del mondo).

    Come posso ottenere la latitudine, la longitudine da x, y su una mappa di Mercatore (JPEG)?

    Ecco un po ‘ di codice (JavaScript, ma facile da seguire) per chiarire.

    Io vivo in Australia, ad una latitudine di circa -33°.

    convertRange(
        GudermannianInv(-33), 
        [Math.PI, - Math.PI], 
        [0, 256]
    );
    

    152.88327883810192

    Se si contano 152 pixel verso il basso dalla parte superiore della piastrella, si trova in Australia. Ho verificato anche questa risposta è corretta, confrontando il risultato di noto-buone funzioni.

    Per essere sicuri, siamo in grado di invertire il processo di calcolo:

    Gudermannian(
        convertRange(
            152.88, 
            [0, 256], 
            [Math.PI, - Math.PI]
    ));
    

    E siamo tornati -32.99613291758226.

    La parte difficile non è in Gudermannian funzione, ma nella conversione tra le due scale.

    Fortunatamente, essendo piuttosto pigro, e di odiare questo tipo di problemi di scalabilità, ho già avuto un po ‘ di funzione per farlo disordinato di conversione per me.

        /**
         * convert number from _n_ of r1[0] .. r1[1] to _n_ of r2[0] .. r2[1]
         * @example `convertRange( 5, [0, 10], [0, 100] ) === 50`
         *
         * @param {number} value
         * @param {array<number>} r1 old range
         * @param {array<number>} r2 new range
         * @returns {number} value adjusted for new range
         */
        function convertRange( value, r1, r2 ) {
            return ( value - r1[0] )
                 * ( r2[1] - r2[0] )
                 /( r1[1] - r1[0] )
                 +   r2[0];
        }
    

    E JavaScript versioni delle funzioni originarie sono naturalmente:

    function Gudermannian(y) {
        return Math.atan(Math.sinh(y)) * (180 /Math.PI)
    }
    
    function GudermannianInv(latitude)
    {
        var sign = Math.sign(latitude);
        var sin  = Math.sin(
                              latitude 
                            * (Math.PI /180) 
                            * sign
        );
        return sign * (
            Math.log(
                (1 + sin) /(1 - sin)
            ) /2
        );
    }
    
  3. 0

    Una nota importante quando si esegue un’inversa è che non c’è nessuna tale cosa come “il mappa di mercatore”, come è il caso con la maggior parte delle altre proiezioni cartografiche. Ogni mappa di mercatore nell’esistenza è diversa a seconda dell’ingresso phi valore. Secondo wikipedia, google utilizza 85.051129, e l’altra mappa di fornitori 85.05113. Pertanto i valori di input per Gudermannian devono essere scalati ad esempio in base GudermannianInv(85.05113).

Lascia un commento