Belirli bir enlem / boylam noktasının 30 km yarıçapındaki tüm sonuçlar döndürülsün mü?


21

Ben the_geombenzer veriler içeren bir sütun içeren bir tablo var :

0103000020E61000000100000005000000CE473AACFA071E40F27FB23340744740336FE841C6231E40873BED903F744740FC150A0ACE231E40D19E2684637647409C9B443D00081E409A9AF82664764740CE473AACFA071E40F27FB23340744740

Fonksiyonu uygularken aşağıdakileri ST_AsEWKT(the_geom)döndürür:

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

Örneğin, belirli bir lat / uzun noktasının 30 km yarıçapında olan tüm verileri seçmeliyim:

  • lat = 46.8167
  • lng = 6.9333

Ancak ne zaman kullanmaya çalışsam ST_Distance(), her zaman 1'den küçük değerler aldım ve kullanmak ST_DWithin()her zaman true değerini döndürdü.

Yanıtlar:


23

Belirli bir mesafeden veri almak için lütfen PostgreSQL için aşağıdaki sorguyu kontrol edin. Umarım yardımcı olur.

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

1
Şununla çalışmayı başardı: SELECT * FROM myTable WHERE GeometryType (ST_Centroid (the_geom)) = 'POINT' VE ST_Distance_Sphere (ST_Point (ST_X (ST_Centroid (the_geom)), ST_Y (ST_Centroid (the_geom))), (6_3 , 46.8167))) <= 18 * 1609.34
dan2k3k4

Harika :)
Farhat Abbas

2
Merak eden herkes için 1609.34 rakamı, milg / s'nin kullandığı ana birim olan mil başına metre. Yani kilometre yapmak için, açıkça 1000 ile çarpın.
1mike12

2
Bilgiçlik taslayan not: 1609.344 tam olarak (tanım gereği)
barrycarter

6

Görünüşe göre geometrinizi bir coğrafya sütununda değil, bir geometri sütununda saklıyorsunuz.
Bu iyi, ama ST_Distance fonksiyonu ölçümleri her zaman metre yerine döndürür. Senin durumunda (4326), bu derece olacak.
Sadece ST_Within ile bir tampon kullanmak da işe yaramaz, çünkü ST_Buffer derece ile ölçülür.

Verilerinizi geometri yerine coğrafyaya dönüştürebilir veya noktanızı metre, arabellek kullanan bir projeksiyona dönüştürebilir ve ardından içinde ne olduğunu görmek için 4326'ya dönüştürebilirsiniz:

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

Bu , web haritaları ile popüler bir projeksiyon olan 3857'ye işaret ediyor . Daha sonra 30.000 metre kadar tamponlar, daha sonra ST_Within'e geçmeden önce 4326'ya yeniden kopyalar.


Bir sözde-Mercator mesafe için güvenilir değildir, bu nedenle veri ekvatora yakın değilse, sonuçlar özellikle 30 km'lik bir mesafe ile kapalı olacaktır.
Vince

6

Benim dünyamda, özel bir SRID (Google Haritalar için) kullanmak böyle bir şey çalıştı:

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

burada tipi locationbir geometri (Nokta, 3785) ve longitude, latitudeve radiusşamandıralardır (örneğin 100W / 44N / 30 "birimler için -100, 44, 30 - aşağıya bakın)

Bkz . Başka bir nesnenin yarıçapındaki tüm nesneleri bulmanın en iyi yolu nedir? postgis dokümanlarında:

Bu ST_DWithin(geometry, geometry, distance)fonksiyon, endeksli bir mesafe araması yapmanın kullanışlı bir yoludur. Mesafe yarıçapını kapsayacak kadar büyük bir arama dikdörtgeni oluşturarak ve ardından dizine alınan sonuçların alt kümesinde tam bir mesafe araması gerçekleştirerek çalışır.

GÜNCELLEME: birimler SRID 3785 için mil değildir ... radyan ya da derece gibi görünürler. Ancak SRID'imin özellikleri, birimlerinin metre veya derece olduğunu ve kesinlikle bunların hiçbiri olmadığını, en azından bir dönüşüm olmadan olmadığını söyledi:

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 (postanızda) ve 3857 arasındaki fark nedir?
ayarlandı

Bunlar farklı projeksiyonlar. 3875 vs 3857 - Birinin diğerinden daha iyi olup olmadığını bilmiyorum
AlexChaffee

1
"EPSG 3785, aksi takdirde özdeş EPSG 3857 lehine kullanımdan kaldırıldı" - github.com/rgeo/rgeo/pull/61
Yarin

2

Bunun işe yarayacağını düşünüyorum:

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

3
Eğer the_geom'u çalışması gereken coğrafyaya çevirirseniz. st_dwithin (coğrafya (the_geom), coğrafya (<Point, 4326>), 30000)
cavila
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.