web-dev-qa-db-ja.com

経度\緯度からデカルト座標への変換

緯度と経度( WGS-84 )として指定された地球中心の座標点があります。

原点を地球の中心にしてデカルト座標(x、y、z)に変換するにはどうすればよいですか?

93
daphshez

最近、WGS-84データで「Haversine Formula」を使用してこれと同様のことを行いました。

はい、WGS-84は地球が楕円体であると想定していますが、「Haversine Formula」のようなアプローチを使用した場合、平均誤差は約0.5%しか得られないと考えています。数フィートの距離について話している場合を除き、常にある程度のエラーが発生します。それでも、理論的には地球の曲率があります。

私はstarblueがどこから来たのか理解していますが、優れたソフトウェアエンジニアリングは多くの場合トレードオフに関するものです。 。たとえば、「マンハッタン距離式」から計算された結果と「距離式」からの結果は、計算的に安価であるため、特定の状況でより良い場合があります。 「どの点が最も近いか」を考えてください。正確な距離測定が必要ないシナリオ。

に関しては、「Haversine Formula」は実装が簡単で、2次元三角法に基づいた「Law of Cosines」ベースのアプローチの代わりに「Spherical Trigonometry」を使用しているため、ナイスです。複雑すぎる。

Chris Venessという名前の紳士は http:/ /www.movable-type.co.uk/scripts/latlong.html これは、興味のあるいくつかの概念を説明し、さまざまなプログラムによる実装を示しています。これは、x/y変換の質問にも答えるはずです。

41
bn.

私が見つけた答えは次のとおりです。

定義を完成させるために、デカルト座標系で:

  • x軸はlong、lat(0,0)を通過するため、経度0は赤道と一致します。
  • y軸は(0,90)を通過します。
  • また、z軸は極を通ります。

変換は次のとおりです。

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)

Rは 地球のおおよその半径 (例:6371KM)です。

三角関数がラジアンを期待する場合(おそらくそうです)、まず経度と緯度をラジアンに変換する必要があります。もちろん、度\分\秒ではなく小数表現が必要です( e.g。here 変換についてを参照)。

逆変換の式:

   lat = asin(z / R)
   lon = atan2(y, x)

asinはもちろんアークサインです。 ウィキペディアでatan2について読む 。ラジアンから度に戻すことを忘れないでください。

このページ は、このためのC#コード(式とは非常に異なることに注意してください)、およびこれが正しい理由の説明とニース図を示します。

116
daphshez

GPS(WGS84)デカルト座標に変換するための理論https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates

以下は私が使用しているものです:

  • GPS(WGS84)の経度とデカルト座標は同じです。
  • 緯度はWGS 84楕円体パラメーターによって変換する必要があります。長径は6378137 mです。
  • 平坦化の逆数は298.257223563です。

私はVBコードを添付しました

Imports System.Math

'Input GPSLatitude is WGS84 Latitude,h is altitude above the WGS 84 ellipsoid

Public Function GetSphericalLatitude(ByVal GPSLatitude As Double, ByVal h As Double) As Double

        Dim A As Double = 6378137 'semi-major axis 
        Dim f As Double = 1 / 298.257223563  '1/f Reciprocal of flattening
        Dim e2 As Double = f * (2 - f)
        Dim Rc As Double = A / (Sqrt(1 - e2 * (Sin(GPSLatitude * PI / 180) ^ 2)))
        Dim p As Double = (Rc + h) * Cos(GPSLatitude * PI / 180)
        Dim z As Double = (Rc * (1 - e2) + h) * Sin(GPSLatitude * PI / 180)
        Dim r As Double = Sqrt(p ^ 2 + z ^ 2)
        Dim SphericalLatitude As Double =  Asin(z / r) * 180 / PI
        Return SphericalLatitude
End Function

hは、WGS 84 ellipsoidよりも高度が高いことに注意してください。

通常、GPSは、上記のHの高さのMSLを示します。 MSLの高さは、geopotentialモデルWGS 84 ellipsoidLemoine et al、1998)を使用して、EGM96より上の高さhに変換する必要があります。
これは、15アーク分の空間解像度でジオイド高さファイルのグリッドを補間することによって行われます。

または、あるレベルprofessionalGPSに高度があるHmsl、heigh上記の平均海面レベル)とUNDULATIONの関係geoidおよび内部テーブルから選択されたdatum出力ellipsoid (m)h = H(msl) + undulationを取得できます

デカルト座標によるXYZへ:

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)
6
Howie

proj.4 ソフトウェアは、変換を実行できるコマンドラインプログラムを提供します。

LAT=40
LON=-110
echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84

また、 C API も提供します。特に、関数pj_geodetic_to_geocentricは、最初に投影オブジェクトを設定することなく変換を行います。

5
Brian Hawkins

すでに実装され、テストで実証されたものを実装するのはなぜですか?

たとえば、C#には NetTopologySuite があり、これはJTS Topology Suiteの.NETポートです。

具体的には、計算に重大な欠陥があります。地球は完全な球体ではなく、地球の半径の近似は正確な測定のためにそれを切断しない場合があります。

自作の関数を使用することが許容される場合、GISは、信頼性の高い、実証済みのライブラリを使用することが好まれている分野の良い例です。

4
Yuval Adam

球体ではなく楕円体に基づいて座標を取得する場合は、 http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF をご覧ください。式と同様に、変換に必要なWGS84定数。

そこにある数式は、参照楕円体表面に対する高度も考慮しています(GPSデバイスから高度データを取得している場合に便利です)。

3
Stjepan Rajko

Python3.xでは、以下を使用して実行できます。

# Converting lat/long to cartesian
import numpy as np

def get_cartesian(lat=None,lon=None):
    lat, lon = np.deg2rad(lat), np.deg2rad(lon)
    R = 6371 # radius of the earth
    x = R * np.cos(lat) * np.cos(lon)
    y = R * np.cos(lat) * np.sin(lon)
    z = R *np.sin(lat)
    return x,y,z
2
Mayank Kumar
Coordinate[] coordinates = new Coordinate[3];
coordinates[0] = new Coordinate(102, 26);
coordinates[1] = new Coordinate(103, 25.12);
coordinates[2] = new Coordinate(104, 16.11);
CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates);

Geometry geo = new LineString(coordinateSequence, geometryFactory);

CoordinateReferenceSystem wgs84 = DefaultGeographicCRS.WGS84;
CoordinateReferenceSystem cartesinaCrs = DefaultGeocentricCRS.CARTESIAN;

MathTransform mathTransform = CRS.findMathTransform(wgs84, cartesinaCrs, true);

Geometry geo1 = JTS.transform(geo, mathTransform);
1
yang jun

Javaでこれを行うことができます。

public List<Double> convertGpsToECEF(double lat, double longi, float alt) {

    double a=6378.1;
    double b=6356.8;
    double N;
    double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
    N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
    double cosLatRad=Math.cos(Math.toRadians(lat));
    double cosLongiRad=Math.cos(Math.toRadians(longi));
    double sinLatRad=Math.sin(Math.toRadians(lat));
    double sinLongiRad=Math.sin(Math.toRadians(longi));
    double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
    double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
    double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;

    List<Double> ecef= new ArrayList<>();
    ecef.add(x);
    ecef.add(y);
    ecef.add(z);

    return ecef;


}
0