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


103

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

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


1
WGS-84の経度と緯度をデカルト座標に変換できましたか?標高もあります。私はここで受け入れられた答えを試しましたが、それは私に正しい答えを与えません。結果を次のWebサイトと比較しました:apsalin.com/convert-geodetic-to-cartesian.aspx
ヤスミン、2015

回答:


45

私は最近、WGS-84データの「Haversine式」を使用してこれと同様のことを行いました。これは、「Haversinesの法則」の派生物であり、非常に満足のいく結果が得られます。

はい、WGS-84は地球が楕円体であることを前提としていますが、「Haversine式」のようなアプローチを使用した場合、平均誤差は約0.5%しか得られないと思われます。数フィートの距離について話していなくても、理論的には地球の曲率がある場合を除いて、常にある程度のエラーが発生します。より厳密なWGS-84互換のアプローチが必要な場合は、「Vincenty Formula」を確認してください。

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

二次元三角法に基づく「コサインの法則」ベースのアプローチの代わりに「球面三角法」を使用しているため、実装が簡単であり、「Haversine Formula」が優れているため、精度のバランスが取れています。複雑さ以上。

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


1
0.5%エラー-何の0.5%?この質問のコンテキストでは、地球の半径である可能性があるため、0.5%は30 kmになる可能性があります:)
MarkJ

2
リンクを確認しました。0.5%の引用は、2点間の大圏距離の誤差のため、この質問には厳密には関係しません。緯度経度を地球の中心を原点とするデカルト座標に変換すると、球形の地球を想定した場合の誤差が大きくなる可能性があると思います。それはquestionnerがしたいどのようなはっきりしないデカルト座標で。奇妙な理由でそれらで作業するほうが便利なのでしょうか、それともデータのエクスポートの要件なのでしょうか?後者の場合、正確さが重要になります。
MarkJ 2009

129

これが私が見つけた答えです:

定義を完全にするために、デカルト座標系で:

  • 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は地球のおおよその半径です(例:6371 km)。

三角関数がラジアンを期待している場合(おそらくそうです)、まず経度と緯度をラジアンに変換する必要があります。明らかに、度\分\秒ではなく、小数表現が必要です(たとえば、変換についてはこちらを参照してください)。

逆変換の式:

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

asinはもちろん逆正弦です。ウィキペディアでatan2について読んでください。ラジアンから度に変換することを忘れないでください。

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


17
-1これは誤りです。WGS-84は楕円体を想定しているのに対して、地球は球体であると想定しています。
starblue

42
@starblue:与えられた回答に「正しい」または「間違った」というラベルを付ける立場にあるかどうかはわかりません。利用可能なlat / lngs(WGS-84を参照)を使用した(ECEFスタイルのx、y、z座標を取得するための)球面近似は、元のポスターのニーズに「適切」であるか、「不十分」です。距離と方位の推定については、この単純な変換で十分だと思います。彼が衛星を打ち上げているなら、多分そうではないでしょう。結局のところ、WGS-84自体は「間違っている」...地球の表面の完全なモデルではないという点です。すべての楕円体モデルは近似です。残念ながら、OPは彼が何をしようとしているかを教えてくれませんでした。
Dan H

10
@Dan H質問はWGS-84を要求します。別のことに答える場合は、少なくとも違い/エラーについて話し合う必要がありますが、この答えはそうではありません。
starblue

@ daphna-shezafは逆変換できません...ラジアンから度への逆変換も行いましたが、結果は同じではありません...

ありがとう、それが機能しない理由を理解するのに1時間費やして、いくつかのcos(lat)とsin(lat)を入れ替えたことが判明
aeroson '30

6

変換のための理論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高さは、高さに変換されなければならないh上記のWGS 84 ellipsoid使用によってジオポテンシャルモデルEGM96ルモワーヌら、1998)。
これは、15分の弧の空間分解能でジオイド高さファイルのグリッドを補間することによって行われます。

または、あるレベルの専門家 GPSが高度Hmsl、平均海面より上の高さ)を持ちUNDULATION、内部テーブルから選択されたデータム出力のgeoidとの関係を持っている場合。得られるellipsoid (m)h = H(msl) + undulation

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

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

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

z = R *sin(lat)

Rの値は何ですか?
eych

4
球の半径だと思いますが、地球は6371kmです。
マティアス

5

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

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

3

球ではなく楕円体に基づいて座標を取得する場合は、http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEFを参照してください。変換に必要な式とWGS84定数が表示されます。

そこでの公式は、参照楕円面に対する高度も考慮に入れます(GPSデバイスから高度データを取得している場合に役立ちます)。


ここにリンクのコンテンツを投稿していませんが、賛成票を投じています。
Mad Physicist、

2

なぜすでに実装され、テスト済みの何かを実装するのですか?

C#には、JTSトポロジスイートの.NETポートであるNetTopologySuiteがあります。

具体的には、計算に重大な欠陥があります。地球は完全な球体ではありません。正確な測定のために、地球の半径の概算では地球をカットできない場合があります。

自作の関数を使用することが許容される場合は、GISは、信頼性が高く、テストで実証されたライブラリを使用することが非常に好ましいフィールドの良い例です。


1
+1。信頼できるライブラリを使用することは、自作の関数より正確であり、また簡単です。
MarkJ 2009

5
NetTopologySuiteは、どのようにしてロング/レイトからカーテションに変換しますか?
ビナヤン2013年

1
NTSには座標変換機能が含まれていません。おそらくProj.NET projnet.codeplex.com
D_Guidi

6
ばかげて、答えは変換機能さえ提供しません。
モート2015年

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

詳しく説明できますか?私、あなたのアプローチを使用して単一の座標を変換するために階層化する単純なアプリケーションを作成しました。ソース(2)のサイズとターゲット(3)のサイズが異なり、例外が発生するため、常に失敗しますjava.lang.IllegalArgumentException: dimension must be <= 3
oschrenk

うーん...私はJTSを少し見てきました。新しいLineString()までの行はJTSのように見えます。しかし、JTSにはCRSやTransformの要素は表示されません。だから:それらはそこにあり、私はそれらを逃していますか?あり、1.12で削除されましたか?または:それは別のライブラリですか?
Dan H

0

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;


}

パラメータaltとは何ですか?
バリマン

高度。GPSの仕組みがわからない場合、ここで何をしていますか;)
MushyPeas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.