9

メルカトル投影図法を JPEG として持っています。指定された x、y 座標を緯度と経度に関連付ける方法を知りたいです。グデルマン関数を見てきましたが、正直なところ、その関数を取得して適用する方法がわかりません。つまり、どのような入力が期待されているのでしょうか? 私が見つけた実装 (JavaScript) は、-PI と PI の間の範囲を取るようですが、ピクセル単位の y 値とその範囲の相関関係は何ですか?

また、緯度を取得して Google マップのタイルを返すこの関数も見つけました。これもメルカトルを使用しています。この関数を逆にする方法を知っていれば、答えにかなり近づいているように思われます。

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

5 に答える 5

3

Erich Mirabal の答えは完全に正しかったです (完全ではないにしても)。

「理論上の 256x256 メルカトル タイル」(Google の世界地図の単一タイル バージョン) を使用してテストしました。

タイル0

説明するためのもう少しのコード (JavaScript ですが、簡単に理解できます) を次に示します。

私は緯度約-33°のオーストラリアに住んでいます。

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

152.88327883810192

タイルの上から 152 ピクセル下を数えると、オーストラリアになります。また、結果を既知の適切な機能と比較することにより、この回答が正しいことを確認しました。

確かに、その計算を逆にすることができます。

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

そして、-32.99613291758226が返されます。

トリッキーな部分はグデルマン関数ではなく、2 つのスケール間の変換にあります。

幸いなことに、かなり怠け者で、この種のスケーリングの問題を嫌っていたので、私はすでにその厄介な変換を行うための小さな関数を持っていました。

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

また、元の関数の JavaScript バージョンは当然次のとおりです。

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
    );
}
于 2016-10-17T10:07:14.577 に答える
2

Google などは、遅くて複雑な楕円方程式ではなく、球状の地球モデルを使用したメルカトル図法である「球状メルカトル」を使用しています。

変換は、OpenLayers コードの一部として利用できます。

http://docs.openlayers.org/library/spherical_mercator.html

于 2009-07-22T15:28:52.623 に答える
0

私は似たようなことをしました。特に、世界の一部からの画像がある場合。トリミングされた地図または完全な世界地図ではない: https://stackoverflow.com/a/10401734/730823

于 2012-05-02T05:40:56.910 に答える