返回特定纬度/经度半径30公里范围内的所有结果?


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公里范围内的所有数据,例如:

  • 纬度= 46.8167
  • lng = 6.9333

但是,每当尝试使用时ST_Distance(),我总是收到小于1的值,并且使用ST_DWithin()总是返回true。

Answers:


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

太好了:)
Farhat Abbas

2
对于其他任何想知道的人,1609.34的数字是每英里米,这是postgres使用的基本单位。所以,我们要做公里,显然乘以1000
1mike12

2
Pedantic笔记:确切来说是1609.344(按定义)
barrycarter

6

听起来您是将几何存储在几何列中,而不是地理列中。
很好,但是函数ST_Distance将以投影单位而不是始终以米为单位返回测量结果。以您的情况(4326)为准。
仅将缓冲区与ST_Within一起使用也不起作用,因为ST_Buffer也会以度为单位。

您可以将数据转换为使用地理而非几何,或者可以将点转换为使用米,缓冲区的投影,然后转换回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中,这是在网络地图中很流行的投影。然后将其缓冲30,000米,然后将其重新投影回4326,然后再传递给ST_Within。


除了伪墨卡托的距离是不可靠的,因此除非数据靠近赤道,否则结果将不正确,尤其是距离为30 km时。
文斯

6

在我的世界中,使用自定义的SRID(适用于Google Maps)是这样的:

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

其中的类型location是一个几何形状(点,3785),和longitudelatituderadius是浮标(例如-100,44,30为100W / 44N / 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有什么区别?
调整

他们是不同的预测。3875 vs 3857-我不知道一个人是否比另一个人更好
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)
cavila
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.