特定のWGS84緯度とWGS84経度、および距離の境界ボックスまたは円を計算できる必要がありますが、どこから始めればよいのかわかりません!
開始緯度/経度からの距離は10Km以下です。
誰かが私にいくつかのポインタを与えることは可能でしょうか/これを行う方法の例
特定のWGS84緯度とWGS84経度、および距離の境界ボックスまたは円を計算できる必要がありますが、どこから始めればよいのかわかりません!
開始緯度/経度からの距離は10Km以下です。
誰かが私にいくつかのポインタを与えることは可能でしょうか/これを行う方法の例
回答:
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ゾーン間で移動したりできます。
データベースでクエリを実行する場合、おそらく高速(不正確)な検索を実行し、その後、結果の場所の距離を正確に計算する必要があります。それはあなたのシナリオですか?
次の関数(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;
}
緯度/経度が境界円の内側か外側かをテストするには、基準緯度/経度からテストする緯度/経度ポイントまでの距離を計算する必要があります。あなたの距離は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度です)。そこから、私はあなたがポールの周りにいないと仮定し、ポリゴンテストでポイントを使用します。
以下は、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 )