8
votes

Comment puis-je obtenir la latitude, la longitude de x, y sur une carte Mercator (JPEG)?

J'ai une carte de projection Mercator en tant que JPEG et j'aimerais savoir comment raconter une coordonnée X, Y donnée à sa latitude et à sa longitude. J'ai regardé la fonction gudermannienne, mais je ne comprends honnêtement pas comment prendre cette fonction et l'appliquer. À savoir, quelle contribution est-elle en attente? La mise en œuvre que j'ai trouvée (JavaScript) semble prendre une gamme comprise entre -PI et PI, mais quelle est la corrélation entre ma valeur Y en pixels et cette gamme?

En outre, j'ai trouvé cette fonction qui prend une latitude et retourne la tuile Pour Google Maps, qui utilise également Mercator. Il semblerait que si je savais comment inverser cette fonction, je serais assez proche d'avoir ma réponse. P>

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


5 commentaires

Si je me souviens bien, Google utilise une projection équitable, pas le merci.


Terre virtuelle et Google utilisent Mercator.


De plus, la latitude maximale utile lorsque vous utilisez Mercator n'est pas de + -90 degrés - il s'agit d'environ + -85,05112878 degrés. La valeur est l'infini sur les pôles, vous devez donc l'ignorer et ignorer les pôles.


Pour vraiment compléter le problème, vous devez également connaître le niveau de zoom lorsque vous travaillez avec des carreaux.


Je suis un peu incertain à ce sujet. Voulez-vous faire (x, y) -> (lat, long) ou (lat, long) -> (x, y)?


5 Réponses :


8
votes

Voici un code pour vous ... laissez-moi savoir si vous avez besoin de plus d'explication.

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


8 commentaires

Donc, si j'ai une image de la carte Mercator 1588 pixels hauts, et je veux connaître la latitude où y = 677, je comprendrais 677 en termes de + PI à -PI et appelez GUDERMANNIAN (Y_IN_TERMS_OF_PI)? Je réalise que c'est faux, mais vous pouvez voir où je suis coincé mentalement ici ...


Par exemple, sur une carte Mercator de 1588 pixels de grande taille, 30.0n est de 615 pixels du haut. Mais si j'exprète 615 en termes d'une gamme linéaire de PI (0) à -PI (1588), je reçois 615 -> 0,70824318. Et appeler les rendements ci-dessus gudermannien (0.70824318) 37.5587, pas 30.0.


De toute évidence, le problème est le «exprimant 615 en termes d'une gamme linéaire». Alors, comment puis-je faire ça?


Vous devez essentiellement faire quelque chose comme ceci: Lat = gudermannian (Ymax - (Y / Hauteur) * (Ymax - Ymin))); Lorsque Ymax et Ymin sont donnés en prenant le gudermannien inverse de + -85.05112878 (ou quelles que soient les limites Max et Min latitudes de votre image sont) et la hauteur est la taille de votre image. Si vous vous cotez, cela fonctionnera également tant que vous remplacez le Ymax et Ymin avec les limites et la hauteur de la tuile avec la taille de la tuile. Cela a-t-il du sens?


defvert_y_to_lat (Y): ymax = gudermannian_inv (gudermannian (math.pi)); Ymin = gudermannian_inv (GUDERMANNIAN (MATH.PI)) * -1; Hauteur = 1588; lat = gudermannian (ymax - ((y / hauteur) * (ymax - ymin))); retourner la lat; Convert_Y_TO_LAT (615) renvoie 4.42964421829. Je m'attendais à revenir 30.0. :-(


Vous ne pouvez pas utiliser PI. Ce n'est que la limite que vous n'arriverez jamais. Au lieu de cela, utilisez la valeur de 85.05112878 degrés (converti en radians).


Je reçois 37.5587 quand y = 615. Pour 30 degrés, tu devrais être 655.17. Qu'est-ce qui vous rend si sûr que 615 == 30 degrés?


Sur mes carreaux du monde entier Mercator, repassés à 1588 hauts, Pixel 615 (du haut) traverse l'Espagne quelque part près de Cartagena et Sicile près de Catane, à environ 37 degrés 32 minutes au nord, donc je ne pense pas que 30.0 est correct.



2
votes

Google, etc., utilisez "Sphérique Mercator", la saillie Mercator utilisant un modèle de terre sphérique plutôt que les équations elliptiques plus lentes et plus complexes.

Les transformations sont disponibles dans le cadre du code OpenLayers:

http://docs.openlayers.org/library/sphérical_mercator.html


0 commentaires

0
votes

J'ai fait quelque chose de similiaire. Surtout si vous avez une image d'une partie du monde. Une carte recadrée ou tout simplement pas une carte complète du monde: https://stackoverflow.com/a/10401734/730823


0 commentaires

0
votes

Une note importante lors de la réalisation d'un inverse est qu'il n'y a pas de " la carte mercator", comme c'est le cas avec la plupart des autres projections de cartes. Chaque carte du Mercator selon l'existence est différente en fonction de la valeur PHI d'entrée. Selon Wikipedia Google utilise le 85.051129, et d'autres fournisseurs de cartes utilisent 85.05113. Par conséquent, les valeurs d'entrée à GUDERMANNIAN doivent être à la base de par exemple. Gudermannianinv (85.05113).


0 commentaires

2
votes

La réponse d'Erich Mirabal a été complètement correcte (si elle n'est pas complètement complète).

Je viens de le tester à l'aide d'un" tuile théorique 256x256 "(version de carreaux unique de Google d'une carte du monde).

tuile0 p>

Voici un peu plus de code ( JavaScript, mais facile à suivre) à l'élucide. P>

Je vis en Australie, à une latitude d'environ -33 °. P> xxx pré>

152.88327883810192 strong> p>

Si vous comptez 152 pixels du haut de la tuile, vous trouverez l'Australie. J'ai également vérifié que cette réponse est correcte en comparant le résultat à des fonctions connues. em> p>

Pour être sûr, nous pouvons inverser ce calcul: P>

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


0 commentaires