緯度と経度 ( WGS-84 ) として指定された地球中心の座標点がいくつかあります。
地球の中心を原点とするデカルト座標 (x、y、z) に変換するにはどうすればよいですか?
緯度と経度 ( WGS-84 ) として指定された地球中心の座標点がいくつかあります。
地球の中心を原点とするデカルト座標 (x、y、z) に変換するにはどうすればよいですか?
これが私が見つけた答えです:
定義を完全にするために、デカルト座標系で次のようにします。
変換は次のとおりです。
x = R * cos(lat) * cos(lon)
y = R * cos(lat) * sin(lon)
z = R *sin(lat)
ここで、R は地球のおおよその半径です(例: 6371 km)。
三角関数がラジアンを想定している場合 (おそらくそうなります)、最初に経度と緯度をラジアンに変換する必要があります。度\分\秒ではなく、明らかに10進数表現が必要です(たとえば、変換についてはこちらを参照してください)。
逆変換の式:
lat = asin(z / R)
lon = atan2(y, x)
asin はもちろん逆正弦です。ウィキペディアでatan2について読んでください。ラジアンから度に戻すことを忘れないでください。
このページでは、このための C# コード (式とは大きく異なることに注意してください) と、これが正しい理由の説明と素敵な図を示します。
私は最近、WGS-84 データの「Haversine Formula」を使用して、これと同様のことを行いました。これは、「Haversine の法則」の派生物であり、非常に満足のいく結果が得られています。
はい、WGS-84 は地球が楕円体であると想定していますが、「Haversine Formula」のようなアプローチを使用した場合、平均エラーは約 0.5% しか得られないと思います。数フィートの距離について話している場合を除き、常にある程度の誤差があり、理論的には地球の曲率が存在します...より厳密な WGS-84 互換アプローチが必要な場合は、「Vincenty Formula. "
starblueがどこから来ているかは理解していますが、優れたソフトウェア エンジニアリングは多くの場合、トレードオフに関係しているため、すべては実行に必要な精度に依存します。たとえば、"Manhattan Distance Formula" から計算された結果と "Distance Formula" からの結果は、計算コストが低いため、特定の状況ではより優れている場合があります。「どのポイントが最も近いか」を考えてください。正確な距離測定を必要としないシナリオ。
「Haversine Formula」に関しては、実装が簡単で、二次元三角法に基づく「コサインの法則」ベースのアプローチの代わりに「球面三角法」を使用しているため、優れた精度のバランスが得られます。複雑さを超えています。
Chris Venessという名前の紳士は、あなたが興味を持っている概念のいくつかを説明し、さまざまなプログラムによる実装を実演する素晴らしいWeb サイトを持っています。これは、x/y 変換の質問にも答えるはずです。
球ではなく楕円体に基づいて座標を取得することに関心がある場合は、Geographic_coordinate_conversionを見てください。これにより、数式が得られます。GEodetic Datumには、変換に必要なWGS84定数があります。
ここでの式では、準拠楕円体の表面を基準にした高度も考慮されています(GPSデバイスから高度データを取得する場合に便利です)。
すでに実装され、テストで証明されているものを実装するのはなぜですか?
たとえば、C# には、JTS トポロジ スイートの .NET ポートであるNetTopologySuiteがあります。
具体的には、計算に重大な欠陥があります。地球は完全な球体ではなく、地球の半径を概算しても正確な測定ができない場合があります。
場合によっては自作関数の使用が許容される場合、GIS は、信頼性が高く、テストで証明されたライブラリを使用することが非常に好まれる分野の良い例です。
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);
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;
}