特定の緯度/経度地点から半径30km以内のすべての結果を返しますか?


21

次のようなthe_geomデータを含む列を持つテーブルがあります。

0103000020E61000000100000005000000CE473AACFA071E40F27FB23340744740336FE841C6231E40873BED903F744740FC150A0ACE231E40D19E2684637647409C9B443D00081E409A9AF82664764740CE473AACFA071E40F27FB23340744740

関数を適用すると、次の結果ST_AsEWKT(the_geom)が返されます。

SRID=4326;POLYGON((7.5077921782085 46.9082092877942,7.53493597966353 46.9081898840296,7.53496566473541 46.9249119938446,7.50781341296434 46.9249314035307,7.5077921782085 46.9082092877942))

特定の緯度/経度ポイントから半径30 km以内にあるすべてのデータを選択する必要があります。次に例を示します。

  • lat = 46.8167
  • lng = 6.9333

ただしST_Distance()、を使用しようとすると、常に1未満の値を受け取り、使用するとST_DWithin()常にtrueが返されます。

回答:


23

特定の距離内のデータを取得するには、PostgreSQLの次のクエリを確認してください。私はそれが役立つことを願っています。

SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34

1
SELECT * FROM myTable WHERE GeometryType(ST_Centroid(the_geom))= 'POINT' AND ST_Distance_Sphere(ST_Point(ST_X(ST_Centroid(the_geom))、ST_Y(ST_Centroid(the_geom)))、(ST_MakePoint(6.9333) 、46.8167)))<= 18 * 1609.34
dan2k3k4

それは素晴らしいです:)
ファーハットアッバス

2
疑問に思う他の人のために、1609.34という数字は1マイルあたりのメートルであり、これはpostgresが使用している基本単位です。したがって、キロメートルを行うには、明らかに1000を掛けます
。– 1mike12

2
知識:正確には1609.344(定義により)
barrycarter

6

ジオメトリ列ではなく、ジオメトリ列にジオメトリを保存しているようです。
それは問題ありませんが、関数ST_Distanceは、常にメートルではなく投影単位で測定値を返します。あなたの場合(4326)、それは度です。ST_Bufferも度で測定さ
れるため、ST_Withinでバッファーを使用するだけでは機能しません。

ジオメトリの代わりに地理を使用するようにデータを変換するか、メートル、バッファーを使用する投影にポイントを変換してから、4326に変換して、その中身を確認できます。

SELECT
    *
FROM <your data>
WHERE ST_Within(the_geom, 
                ST_Transform(ST_Buffer(ST_Transform(ST_SetSRID(ST_MakePoint(6.9333, 46.8167), 4326), 3857), 30000), 4326)) = 1

これは、ポイントを3857に投影します。これは、Webマップで一般的な投影法です。次に、30,000メートルずつバッファリングし、ST_Withinに渡す前に4326に再投影します。


擬似メルカトルは距離が信頼できないので、データが赤道に近い場合を除き、特に30kmの距離では結果がオフになります。
ビンス

6

私の世界では、カスタムSRID(Googleマップ用)を使用すると次のようになりました:

SELECT * FROM addresses WHERE ST_DWithin(location, ST_SetSRID(ST_MakePoint(longitude, latitude), 3785), radius);

種類は、ここでlocationジオメトリ(ポイント、3785)であり、そしてlongitudelatitude、及びradius(100W / 44N / 30 "単位"のため、例えば-100、44、30 -下記参照)浮動小数点数であります

他のオブジェクトの半径内にあるすべてのオブジェクトを見つける最良の方法は何ですか?を参照してくださいpostgisドキュメント:

このST_DWithin(geometry, geometry, distance)関数は、インデックス付き距離検索を実行する便利な方法です。距離半径を囲むのに十分な大きさの検索長方形を作成し、結果のインデックス付きサブセットで正確な距離検索を実行することにより機能します。

更新:単位はSRID 3785のマイルではありません...それらはラジアンか度、またはそのようなもののようです。しかし、私のSRIDの仕様では、その単位はメートルまたは度のいずれかであり、少なくとも変換なしではないことは間違いありません。

alex=# select * from spatial_ref_sys where srid=3785; srid | auth_name | auth_srid | srtext | proj4text
3785 | EPSG | 3785 | PROJCS["Popular Visualisation CRS / Mercator (deprecated)",GEOGCS["Popular Visualisation CRS",DATUM["Popular_Visualisation_Datum",SPHEROID["Popular Visualisation Sphere",6378137,0,AUTHORITY["EPSG","7059"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6055"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4055"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3785"],AXIS["X",EAST],AXIS["Y",NORTH]] | +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs


(投稿の)3785と3857の違いは何ですか?
調整

それらは異なる投影です。38753857-あるものが他のものより優れているかどうかはわかりません
-AlexChaffee

1
「EPSG 3785は廃止され、それ以外は同一のEPSG 3857が採用されました」-github.com/rgeo/rgeo/pull/61
Yarin

2

私はこれがうまくいくと思う:

SELECT gid FROM table 
WHERE ST_DWithin(the_geom, ST_SetSRID(ST_Point(6.9333, 46.8167), 4326), 30000)

3
the_geomを動作する地理にキャストした場合。st_dwithin(geography(the_geom)、geography(<Point、4326>)、30000)
カビラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.