緯度と経度の代わりに(またはそれに加えて)位置座標を3D空間に変換し、x、y、およびzの列を使用して、データベース構造を変更することができます。 zはメートル単位です。
SELECT * FROM location
WHERE location.x BETWEEN center.x - 300 AND center.x + 300
AND location.y BETWEEN center.y - 300 AND center.y + 300
AND location.z BETWEEN center.z - 300 AND center.z + 300
これはあなたのリストをきれいに整えてくれます。結果セットのhaversine計算を行うことができます。
緯度と経度のみのデータベースを使用している場合は、検索範囲を絞り込むことができます。緯度は簡単です。極に近づくと発生する合併症を無視する限り、南北の1度の緯度は常に111kmの距離に相当します。つまり、300mの距離が0.0027 ...緯度ですが、少し控えめで、0.003または0.004を使用することもできます。
経度は、あなたが南北にどれほど離れているかによって変わりますが、それほど複雑ではありません。緯度の余弦を乗算するだけです。
distance = cos(latitude) * 111.19... km/degree * delta_angle
赤道では、緯度と同じです。赤道での経度の1度の変化は111kmです。北緯80度(または南緯)では、cos(80 degrees) = 0.17...
の係数を掛けます。その結果、経度の1度の変化はわずか19.3kmです。あなたの目的のために、これを逆転させ、300 m/cos(latitude)/(111.19... km/degree) = (0.0027... degrees)/cos(latitude)
として選択するために経度の範囲を見つけることができます。その係数は最初の段落と同じ量です。それは偶然ではありません。
極限に近づくと、座標系の不連続点の近くに問題が発生します。あなたは89.9996度のような緯度に差し込む開始なぜときには見ることができます:唯一の360度全円であるとき
0.0027... degrees/cos(89.9996 degrees) = 386... degrees
さて、どのようにそれをすることができますか?これは、あなたの300mの半径がポールの周りに広がって、話す方法であなたの出発地点を含むように戻ってきたという指標です。その時点で、データベース内のすべてのポイントをポールの近くで検索するだけでよいでしょう。もちろん、89.999度程度でこれをやってみるべきです。なぜなら、あなたが探している領域の直径600mのところが極を完全に囲んでいるからです。
インターナショナル・デイト・ライン、またはより正確には「アンチメリディアン」にはもう1つの問題があり、経度の-180度から+180度までのジャンプに関連しています。赤道上の+ 179.9999度と-179.9999度の地点は、地理的にわずか数メートル離れていても非常に異なる座標を持ちます。より詳細な検索のための予備フィルタとしてこれをやっているだけなので、antimeridianの0.006度(それはおおよそ300mの半径の円の直径です)の範囲内のすべての点を通過するのが最も簡単でしょう。そしてhaversine計算によってポイントが実際に近いかどうかが判断されます。
要約すると、上記の緯度と経度の範囲を使用することができ、極とアンチメリディアンの特殊なケースを追加するだけです。擬似SQL /コードハイブリッドのいくつかの種類では:
:あなたが潜在的に2倍のポイントをテストすることを犠牲にして簡潔な声明をしたい場合は
IF abs(center.latitude) > 89.999
SELECT * FROM location WHERE abs(location.latitude - center.latitude) < 0.003
ELSE
IF abs(center.longitude) > 179.997
SELECT * FROM location
WHERE abs(location.latitude - center.latitude) < 0.003
AND 180 - abs(location.longitude) < (0.006/cos(center.latitude))
ELSE
SELECT * FROM location
WHERE abs(location.latitude - center.latitude) < 0.003
AND abs(location.longitude - center.longitude) < (0.003/cos(center.latitude))
ENDIF
ENDIF
、あなただけの経度の絶対値を比較することができます
SELECT * FROM location
WHERE abs(location.latitude - center.latitude) < 0.003
AND abs(abs(location.longitude) - abs(center.longitude)) <= min(0.003/cos(center.latitude), 180)