緯度/経度座標の最も効率的な表現を知っている人はいますか? 精度レベルは、民生用 GPS デバイスには十分なはずです。
ほとんどの実装ではdouble
各ユニットを使用しているようですが、float
または固定小数点形式で十分であるとは思えません。これらの値の大規模な配列を圧縮または保存しようとした人から聞いてみたいと思います。
編集:
言い換えれば、消費者レベルのデバイスの緯度/経度を表すために必要な最小精度は?
緯度/経度座標の最も効率的な表現を知っている人はいますか? 精度レベルは、民生用 GPS デバイスには十分なはずです。
ほとんどの実装ではdouble
各ユニットを使用しているようですが、float
または固定小数点形式で十分であるとは思えません。これらの値の大規模な配列を圧縮または保存しようとした人から聞いてみたいと思います。
編集:
言い換えれば、消費者レベルのデバイスの緯度/経度を表すために必要な最小精度は?
個人的には、Evan の回答と私のコメントに従って、32 ビットの 10 進固定小数点表現を 1,000,000 で割って使用します。
ただし、スペースが本当に貴重な場合は、いくつかの追加のアイデアを次に示します。
ワイヤ上で 26 ビットの固定小数点表現を使用できます。これには、緯度と経度を大量のバイト配列にマーシャリングおよびアンマーシャリングする必要がありますが、32 ビット値表現よりも位置ごとに 12 ビット (ほぼ 19% の節約) を節約できるため、価値があるかもしれません。
極に近づくほど、経度の値に必要な精度が低くなるという事実を利用できます。赤道では 26 ビット分しか必要ありません。したがって、経度をエンコードするために使用されるビット数が緯度の値に依存するスキームを作成できます。
データに他の圧縮可能な属性がある場合 (たとえば、すべてのポイントが通常非常に近接している場合)、デルタ コーディング スキーム (最初のポイント以外の各ポイントを最後のポイントからのデルタとしてエンコードできる) を使用するなど、それらの特定の利点を利用できます。点)。
編集:コメントからいくつかのポイントを追加しました.32ビット値は十分な精度を提供できるはずです.
32 ビットの固定小数点表現を使用します。値が次の場合:
42.915512
、in-99.521654
を保存します(負の値になる可能性があります)。values * 100000
int32_t
int32_t lat = 42915512;
int32_t lon = -99521654;
これは、単純さと正確さの間の適切な妥協5
点です (通常、小数点で十分です。必要に応じて、いつでも値を上げて1000000
取得6
できます)。
ユーザーに表示するには、cafが提案することを行います。
... ユーザーに表示するには - 整数除算とモジュロを使用します。
printf("Lat = %d.%06d\n", lat / 1000000, abs(lat) % 1000000)
相対的な順序が維持されるため、これらは効率的な方法で比較/ソート可能になります。
EDIT:追加の利点は、ネットワーク経由で送信したり、ポータブルな方法でバイナリ形式でディスクに保存したりできることです。
地球の円周は約です。40.000 km または 24900 マイル。
GPS の精度を 1 桁上回るには、1 メートルの精度 (3 フィート) が必要です。
したがって、40.000.000 の異なる値を格納するには精度が必要です。これは、少なくとも 26 ビットの情報です。32 ビットの float または int が適しています。
地球が半径 'R' 3959 マイル (または ×5280 フィート/マイル = 20903520 フィート) の完全な球体 (そうではありませんが、十分に近い) であると仮定すると、円周は 131340690 フィート (2×PI×R を使用) です。 .
経度 360 度は 131340690 フィートをカバーします。180 度の緯度は 65670345 フィートをカバーします。
緯度/経度を 3 フィートの精度で保存する場合は、43780230 (131340690/3) の経度値と 21890115 (65670345/3) の緯度値を保存できる必要があります。43780230 の保存には 25.38 ビット (log(43780230)/log(2)) が必要で、21890115 の保存には 24.38 ビット (log(21890115)/log(2)) が必要です。
したがって、明らかな問題は、緯度と経度をわずか 6 バイトで格納したい場合、精度はどのくらいになるでしょうか? まあ、6バイトは48ビットです。これは、緯度が 23.5 ビット、経度が 24.5 ビットであることを意味します (経度には 2 倍の値があり、これは 1 ビットであり、24.5-23.5 = 1 ビットです)。したがって、23.5 ビットを使用すると、0 から 11863282 (11863283 値) までの数値を表すことができます。また、65670345 フィートを 11863283 値で割ると 5.53 フィートになります (経度の精度値も同じです)。
結論: したがって、緯度と経度の両方で 5.5 フィートの精度を維持できる場合は、両方の値をわずか 6 バイトにまとめることができます。
*補足: 緯度と経度は、球の周りの位置情報を格納するのに適していないというコメントについては (極に格納する情報が少ないため)、それらのコメントは数学に耐えられません! それを理解しましょう。地球のすべての平方フィートの中心にある地面に記録して杭を立てることができる、新しい完全なシステムを設計したいとしましょう。地球の表面積 (R は 3959 マイル、球体の表面積の公式) は 5490965469267303 SQ FT で、多くの杭を表すには 52.29 ビットが必要です。現在、既存の緯度経度システムは長方形システムを使用しています。長方形の幅は地球の円周で、長方形の高さは円周の 1/2 です) – これは 131340690 * 65670345 (上記を参照)、または 8625188424838050 平方フィート – これには 52 が必要です。表すには 94 ビット (このシステムは、ポールの周囲の地面に「多すぎる」杭を配置します)。したがって、ショッキングな答えは、新しい完全なシステムと古い緯度/経度システムの両方が、地球上の単一の位置を 1 フィートの精度で保存するために実際に 53 ビットを必要とするということです!
フロートは、消費者レベルの GPS デバイスが要求される精度に近い場合でも、GPS 座標を格納するのに十分すぎるほどです。これが真実だと思わない場合は、次の 2 つの簡単な実験を試してください。
私は何年もの間、GPS 対応の PDA 用のアプリケーションを作成してきましたが、これを疑わしい顧客に対して何度も検証してきました (この方法で賭けに勝ったことさえあります)。これよりも正確な精度を達成する高品質の GPS デバイスがありますが、より高価なチップセットを使用するとより高い精度が得られ、デバイスを 1 か所に数日または数週間放置し、時間の経過とともに読み取り値を平均化します。
4 バイトの float は、デバイス自体よりもはるかに正確です。もちろん、2X 係数が問題にならない限り、代わりに double を使用しても問題はありません。
経度 179 度での 23 ビットの精度は、通常の GPS デバイスが提供する最高の精度である 10 メートル未満です。赤道で:
% gps distance "0.0, 179.0" "0.0, $((179 * (1 + 2**-23)))"
From 0.0, 179.0 to 0.0, 179.00002133846283 is 7.79 feet E
From 0.0, 179.0 to 0.0, 179.00002133846283 is 2.38 meters E
そのため、C コンパイラで として認識される IEEE 754 単精度浮動小数点数は、float
表現には十分です。拡張計算に float を使用することに注意してください! 丸め誤差はあなたの昼食を食べるかもしれません。数値アナリストに相談してください。
Garmin の IMG マップ形式では、ボックスのエッジを設定するためにフロートを使用してバウンディング ボックス内に座標を格納します。ボックス内の座標は、必要な精度に応じて最小値と最大値の間でちょうど線形である可変数のビットを使用して定義されます。
例: minlat=49.0, maxlat=50.0, minlon=122.0, maxlon=123.0, ビット数=16
したがって、32768,32768 の値は
49.5, 122.5
16384,0 に変換され、49.25, 122.0 になり
ます。精度が低く、同じ出力がビット数 = 4 で生成される可能性があります
8,8 は 49.5、122.5 に変換され
ます 4,0 は 49.25、122.0 になります
これらの値の大規模な配列を格納する場合、デルタ圧縮を実行してデルタを格納する場合、いくつかの簡単なトリックがあり、データ ストリームのサイズを大幅に削減できます。「キーポイント」からデルタを実行できます
KDDDDDDDDDDKDDDD ...
k + d 任意の d ポイントに移動します
デルタはすべて前の K を参照するため、任意のポイントを再構築するには、K と D が必要です。
または増分デルタを実行できます
キイイイイイイク
これには、目的の位置に到達するまでに複数の合計が必要になる場合があります。しかし、データは全体的に小さくなっています。再構築するSO
k+i+i+i で 4 番目のポイントに到達
最後に、両方を組み合わせることができます
KDIIIDIIIDIIIK
これは、IPB フレームを使用した mpeg-2 に似ていますが、この方法では、どの位置に対しても合計が 4 つを超えることはなく、デルタ圧縮とインクリメンタル圧縮の利点がいくらか得られます。
再帰的なタイル システムを使用する場合、緯度と経度の両方の値を 1つの 32 ビット整数にパックできます。解像度は最悪でも ~2.4 メートル/ピクセル (赤道で) です。レベルごとに 2 ビットを使用すると、16 レベルを 32 ビットで格納できます。Virtual Earth のタイル システムに関するこの記事を見ると、それがどのように機能するかについてのアイデアを得ることができます。これはメルカトルを使用しているため、極の問題が発生します。代わりに別の投影法を使用しても、非常によく似た結果が得られます。
これは、最初の N ビットが同じであるため、特定の親タイル内の任意のポイントを見つけるための大まかなフィルターにも使用できます (そのため、検索はビット マスキングになります)。
long / latが球にデータを保存するためのひどい方法であるという事実を誰も投稿していないことに私は驚いています(経度は極の近くでより低い精度を必要とするという人がいました)。
基本的に、データ位置をメートル単位のXおよびY座標として保存できます。正確にフィットする地球の周りの立方体を想像してみてください(ハハOK 、ほぼフィットします)。3番目の座標は地球の平方根から来る可能性があるため、3つの座標すべてではなく、XとYの位置を格納するだけで済みます。r=平方根[x ^ 2 + y ^ 2 + z ^ 2] 。
したがって、緯度/経度をメートル単位のx/yに変換します。必要なのは、座標ごとに合計12756200m(地球の直径)だけです。したがって、合計値は0から25,512,400(long / latを使用していたため他の誰かが40,000,000と主張)にまたがるだけで、+/-0.5mの精度になります。
その結果、位置ごとにわずか25ビットになります。もし私があなたなら、2m以内の精度で、位置ごとに24ビットを使用します。これは、きちんとした3バイトです。
また、ウェイポイント情報をパスに保存している場合は、各ウェイポイントを最後のウェイポイントからのオフセットとして保存できます。24ビットのx/y座標から始めるように。そして、x/yメーターを加算/減算することによって位置を調整する16ビットの「更新」があります。16ビットを使用すると、ウェイポイントの更新を400m以上離れることができます。したがって、デバイスが飛行機用ではなく、頻繁に更新されることがわかっている場合は、これも許容できる可能性があります。