距離と緯度/経度を指定して境界ボックスを計算する方法


13

特定のWGS84緯度とWGS84経度、および距離の境界ボックスまたは円を計算できる必要がありますが、どこから始めればよいのかわかりません!

開始緯度/経度からの距離は10Km以下です。

誰かが私にいくつかのポインタを与えることは可能でしょうか/これを行う方法の例


どちらのポールもカバーしていないサークルについては、gis.stackexchange.com / questions / 19221 /…で詳細な回答が提供されています。しかし、これは完全な話ではありません。現在の回答が示唆しているように、速度と精度とプログラムの複雑さのトレードオフを行うことができます。また、lat-lonで作業する場合、境界ボックスを指定するときに「ラップアラウンド」問題があることに注意してください(+ -180度子午線で問題が発生します)。これに対する解決策については、gis.stackexchange.com / questions / 17788 /…を参照してください。
whuber

あなたは本当に箱が必要ですか、それとも与えられた点の近くの4点で十分でしょうか?点pが与えられた場合、pからNE、SW、SE、およびNWの方向に4つの点d距離を見つけます。
カーククイケンドール

@カーク-4点の座標がある場合、ボックスがあります
...-martinstoeckli

@martinstoeckli右、私はちょうど球に投影されたボックスがどのように見えるかを視覚化する必要がないことによって問題を簡素化することを望んでいました。また、問題を一般化して、ボックスの側面が同じ緯度/経度(言い換えると、回転したボックス)にある必要がないことを明確にすることができます。
カーククイケンドール

@Kirk-ああ、まあ、まさにそれが必要なのなら、あなたはもちろん正しい。このボックスは、可能な候補をすばやく見つけるためにのみ役立つと思います。2つのポイントが特定の距離(円)内にあるかどうかを確認するには、より複雑なHaversine式を使用できます。
martinstoeckli

回答:


15

WGS-何?WGS-84?必要な精度に応じて、より多くの情報を知る必要があるかもしれません-私が推測するのはあなたが反対票を投じられた理由です。

次の2つの方法があります。

不正確だが、おそらく「十分」

1度の緯度は、WGS-84データムを使用した場合、約10001.965729 / 90キロメートル(赤道から極までの距離を90度で割った値)または111.113キロメートルです。これは、地球の形状と、極に近づくにつれて距離が変化するため、近似値です(経度ではなく緯度を使用する1つの理由-最終的には経度1度の距離はゼロです!)地球も完全ではありません球。これらは両方とも、2番目の答えで、より複雑な投影およびデータベースのアプローチを使用する理由です。

10001.965729km = 90 degrees
1km = 90/10001.965729 degrees = 0.0089982311916 degrees
10km = 0.089982311915998 degrees

これは度/分/秒ではなく小数度を使用しています。

したがって、境界ボックスは、プラスマイナス0.08999度のポイントになります。あるいは、この数値を半径として使用して、境界円を与えることもできます。

これを読んでいるGISの人はぞっとするでしょう。ただし、世界のどこにいるかにもよりますが、ほとんど正確です。半径10kmの場合は問題ありません。

はるかに正確ですが、より多くのコード

投影ライブラリを使用して、データムなどを指定します。Proj4をお勧めします。広く使用されているため、Googleは質問に関する結果の山を返します。Delphi ラッパーもあります。使用に問題がある場合は、SOに別の質問を投稿してください。この質問の範囲外です。Proj4 Webサイトには、基本的なAPIを使用した例があります。これらはCにありますが、かなり簡単に翻訳できるはずです。彼らのAPIリファレンスは、続いて開始するのに最適な場所ですよくある質問

使用したい特定のデータを知らない限り、または座標の作成に使用した場合を除き、WGS-84を基本データム(地球の表現)として使用します。一般的に使用され、かなり正確です。

(たとえば)Googleマップからの位置の場合、メルカトル図法を指定します。別の投影法を使用するか、UTM座標を使用することができます緯度と経度の代わりに、データのソースに応じて、また小さなローカルエリアの高精度が必要な場合。(UTMには複数のゾーンがあり、そのすべてが歪みを変更するため、そのゾーン内は非常に正確です。ゾーンの外側の座標にゾーンを使用すると、遠ざかるにつれて歪みが大幅に増加します。ゾーンは認識できないかもしれませんが、ゾーン内では、UTMの翻訳は可能な限り良好になります。通常、座標は度ではなくメートルで指定されるため、10 kmが必要な場合はより便利です半径10 kmは簡単に1つのゾーン内にありますが、中心座標に基づいて適切なゾーンを選択する必要があります。唯一注意が必要なのは、国境に近づくときです。どちらを使用するかを選択する方法に一貫性があります。また、Proj4では投影を変換できるため、メルカトルWGS-84緯度/経度からUTMゾーンnに移動したり、2つのUTMゾーン間で移動したりできます。


2
私たちが住んでいるところでは、ある測量士が、彼の精神的な計算に1度はおよそ108 kmを使用すると言っていました。精神的に10 kmは約0.1度です。これらは0.089982311915998ではなく1桁(最大で2または3)の精度で処理するのに最適な大まかな近似であるため、精度のレベルを意味します。
スティーブンクアン

1
緯度を考慮して、より正確な角度を計算することは本当に難しくありません。コンピューターが計算を行うため、近似では何も得られません(私の例の最初の関数を参照)。
-martinstoeckli

3

データベースでクエリを実行する場合、おそらく高速(不正確)な検索を実行し、その後、結果の場所の距離を正確に計算する必要があります。それはあなたのシナリオですか?

次の関数(PHPでは申し訳ありません)は、緯度と経度の差を大まかに計算します。この違いは、検索ポイントの緯度に依存します。それらを(わずかな許容範囲で)使用して、データベースで高速検索を行います。このボックスは、緯度+ -deltaLatitudeおよび経度+ -deltaLongitudeで簡単に計算できます。

deltaLatitude[rad] = distance[m] / earthRadius[m]
deltaLongitude[rad] = distance[m] / (cos(latitude[rad]) * $earthRadius[m])

/**
 * Calculates the deltas in latitude and longitude to use, for a db search
 * around a location in the database.
 * @param float $distance Radius to use for the search [m]
 * @param float $latitude Latitude of the location, we need the angle deltas for [deg decimal]
 * @param float $deltaLatitude Calculated delta in latitude [deg]
 * @param float $deltaLongitude Calculated delta in longitude [deg]
 * @param float $earthRadius Mean earth radius in [m]
 */
public static function angleFromSphericDistance($distance, $latitude,
  &$deltaLatitude, &$deltaLongitude, $earthRadius = 6371000)
{
  $lat = deg2rad($latitude);

  $radiusOnLatitude = cos($lat) * $earthRadius;
  $deltaLatitude = $distance / $earthRadius;
  $deltaLongitude = $distance / $radiusOnLatitude;

  $deltaLatitude = rad2deg($deltaLatitude);
  $deltaLongitude = rad2deg($deltaLongitude);
}

半正矢式は、球面上の距離を計算することができます。「正確な」距離を取得するために、見つかった場所のそれぞれに使用します。この方法では、2つの場所が特定の半径内にあるかどうかをテストできます(ボックスではなく円)。

/**
 * Calculates the great-circle distance between two points, with
 * the Haversine formula.
 * @param float $latitudeFrom Latitude of start point in [deg decimal]
 * @param float $longitudeFrom Longitude of start point in [deg decimal]
 * @param float $latitudeTo Latitude of target point in [deg decimal]
 * @param float $longitudeTo Longitude of target point in [deg decimal]
 * @param float $earthRadius Mean earth radius in [m]
 * @return float Distance between points in [m] (same as earthRadius)
 */
public static function haversineGreatCircleDistance(
  $latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
  // convert from degrees to radians
  $latFrom = deg2rad($latitudeFrom);
  $lonFrom = deg2rad($longitudeFrom);
  $latTo = deg2rad($latitudeTo);
  $lonTo = deg2rad($longitudeTo);

  $latDelta = $latTo - $latFrom;
  $lonDelta = $lonTo - $lonFrom;

  $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
    cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
  return $angle * $earthRadius;
}

3

緯度/経度が境界円の内側か外側かをテストするには、基準緯度/経度からテストする緯度/経度ポイントまでの距離を計算する必要があります。あなたの距離は10km以下なので、単純化のため、HaversineではなくEquirectangular近似を使用して距離を取得します。kmで距離を取得するには:

x = (lonRef - lon) * cos ( latRef )
y = latRef - lat
distance = EarthRadius * sqrt( x*x + y*y )

重要な注意:これらの式の緯度/経度は度ではなくラジアンです。EarthRadiusの一般的な値は6371 kmで、km単位で距離を返します。これで、距離が円の内側または外側にあるかどうかを簡単にテストできます。境界円が機能する場合、私はそれで行きます。

境界の四角形の場合、赤道に平行に定義された四角形が必要だと思います。次に、範囲/方位計算を使用して境界ボックスの角を計算します(方位は45度、135度、225度、315度です)。そこから、私はあなたがポールの周りにいないと仮定し、ポリゴンテストでポイントを使用します。


2

以下は、SQL-Server 2012で境界ボックスを作成するために使用するT-SQLコードです。私の場合、Lat、Longの10進数値を取得します。SQL STDistance関数を使用して結果が実際に特定の距離内にあることを確認する前に、これを使用して行数をすばやく制限します。地理関数はSQL Serverで非常にコストがかかるため、バウンディングボックスを構築することにより、実行する必要がある回数を大幅に減らすことができます。

DECLARE @Lat DECIMAL(20, 13) = 35.7862
   ,@Long DECIMAL(20, 13) = -80.3095
   ,@Radius DECIMAL(7, 2) = 5
   ,@Distance DECIMAL(10, 2)
   ,@Earth_Radius INT = 6371000;

SET @Distance = @Radius * 1609.344;

DECLARE @NorthLat DECIMAL(20, 13) = @Lat + DEGREES(@distance / @Earth_Radius)
   ,@SouthLat DECIMAL(20, 13) = @Lat - DEGREES(@distance / @Earth_Radius)
   ,@EastLong DECIMAL(20, 13) = @Long + DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)))
   ,@WestLong DECIMAL(20, 13) = @Long - DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)));

SELECT *
    FROM CustomerPosition AS cp
    WHERE (
            cp.Lat >= @SouthLat
            AND cp.Lat <= @NorthLat )
        AND (
              cp.Long >= @WestLong
              AND cp.Long <= @EastLong )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.