Javaで緯度と経度を2Dポイントに変換する

Javaで緯度と経度を2Dポイントに変換する

 

1. 概要

マップを使用するアプリケーションを実装する場合、通常、座標変換の問題が発生します。 ほとんどの場合、convert latitude and longitude to a 2D point to displayにする必要があります。 幸いなことに、この問題を解決するために、メルカトル図法の式を利用できます。

このチュートリアルでは、メルカトル図法について説明し、その2つのバリアントを実装する方法を学習します。

2. メルカトル図法

Mercator projectionは、1569年にフランドルの地図製作者ゲラルドゥスメルカトルによって導入された地図投影法です。 地図投影は、地球上の緯度と経度の座標を平面上の点に変換します。 つまり、it translates a point on the surface of the earth to a point on a flat mapです。

メルカトル図法を実装するには2つの方法があります。 The pseudo Mercator projection treats the Earth as a sphere. The true Mercator projection models the Earth as an ellipsoid。 両方のバージョンを実装します。

両方のメルカトル図法実装の基本クラスから始めましょう。

abstract class Mercator {
    final static double RADIUS_MAJOR = 6378137.0;
    final static double RADIUS_MINOR = 6356752.3142;

    abstract double yAxisProjection(double input);
    abstract double xAxisProjection(double input);
}

このクラスは、メートルで測定された地球の大半径と小半径も提供します。 地球が球体ではないことはよく知られています。 そのため、2つの半径が必要です。 まず、major radius is the distance from the center of the earth to the equatorです。 次に、minor radius is the distance from the center of the earth to the north and south poles

2.1. 球形メルカトル図法

擬似投影モデルは、地球を球体として扱います。 地球がより正確な形状に投影される楕円投影とは対照的です。 このアプローチにより、quick estimationをより正確に、しかし計算上より重い楕円投影法にすることができます。 その結果、この予測の直接のmeasurements of distancesは概算になります。

さらに、マップ上の図形の比率はわずかに変化します。 その緯度と、国、湖、川などの地図上のオブジェクトの形状の比率の結果として precisely preservedではありません。

これは、Web Mercatorプロジェクションとも呼ばれ、Googleマップなどのウェブアプリケーションで一般的に使用されています。

このアプローチを実装しましょう:

public class SphericalMercator extends Mercator {

    @Override
    double xAxisProjection(double input) {
        return Math.toRadians(input) * RADIUS_MAJOR;
    }

    @Override
    double yAxisProjection(double input) {
        return Math.log(Math.tan(Math.PI / 4 + Math.toRadians(input) / 2)) * RADIUS_MAJOR;
    }
}

このアプローチで最初に注意することは、このアプローチが地球のradiusone constantで表し、実際の2つではないという事実です。 次に、x-axis projectiony-axis projectionへの変換に使用する2つの関数を実装したことがわかります。 上記のクラスでは、Javaが提供するMathライブラリを使用して、コードを単純化しています。

簡単な変換をテストしてみましょう。

Assert.assertEquals(2449028.7974520186, sphericalMercator.xAxisProjection(22));
Assert.assertEquals(5465442.183322753, sphericalMercator.yAxisProjection(44));

この投影法により、ポイントが(-20037508.34、-23810769.32、20037508.34、23810769.32)の境界ボックス(左、下、右、上)にマップされることに注意してください。

2.2. Elliptical Mercator Projection

真の投影法は、地球を楕円体としてモデル化します。 This projection givesaccurate ratiosfor objects anywhere on Earth。 確かに、it respects objects on the map butnot 100% accurate。 ただし、このアプローチは計算が複雑であるため、最も頻繁に使用されるわけではありません。

このアプローチを実装しましょう:

class EllipticalMercator extends Mercator {
    @Override
    double yAxisProjection(double input) {

        input = Math.min(Math.max(input, -89.5), 89.5);
        double earthDimensionalRateNormalized = 1.0 - Math.pow(RADIUS_MINOR / RADIUS_MAJOR, 2);

        double inputOnEarthProj = Math.sqrt(earthDimensionalRateNormalized) *
          Math.sin( Math.toRadians(input));

        inputOnEarthProj = Math.pow(((1.0 - inputOnEarthProj) / (1.0+inputOnEarthProj)),
          0.5 * Math.sqrt(earthDimensionalRateNormalized));

        double inputOnEarthProjNormalized =
          Math.tan(0.5 * ((Math.PI * 0.5) - Math.toRadians(input))) / inputOnEarthProj;

        return (-1) * RADIUS_MAJOR * Math.log(inputOnEarthProjNormalized);
    }

    @Override
    double xAxisProjection(double input) {
        return RADIUS_MAJOR * Math.toRadians(input);
    }
}

上の図では、このアプローチがy軸の投影に関してどれほど複雑であるかがわかります。 これは、丸くない地球の形状を考慮する必要があるためです。 真のメルカトル図法は複雑に見えますが、球形法よりも正確で、地球を1つのマイナーと1つのメジャーで表すために半径を使用します。

簡単な変換をテストしてみましょう。

Assert.assertEquals(2449028.7974520186, ellipticalMercator.xAxisProjection(22));
Assert.assertEquals(5435749.887511954, ellipticalMercator.yAxisProjection(44));

この投影は、ポイントを(-20037508.34、-34619289.37、20037508.34、34619289.37)の境界ボックスにマッピングします。

3. Conclusion

緯度と経度の座標を2Dサーフェスに変換する必要がある場合は、メルカトル図法を使用できます。 実装に必要な精度に応じて、球形または楕円形のアプローチを使用できます。

いつものように、この記事のコードはover on GitHubです。