我有一个带有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公里以内的所有数据,例如:


lng = 6.9333

但是无论何时我尝试使用ST_Distance(),我总是收到小于1的值,而使用ST_DWithin()总是返回true。

评论

文斯(Vince)的漂亮回答:gis.stackexchange.com/questions/247113/…

#1 楼

请检查以下查询PostgreSQL,以获取一定距离内的数据。希望对您有所帮助。

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


评论


能够使用它: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
13年11月11日在16:57

那很棒 :)

–Farhat Abbas
13年11月11日在20:48

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

– 1mike12
18年6月27日在22:01

Pedantic笔记:确切地是1609.344(根据定义)

–user1462
18年8月17日在16:32

#2 楼

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

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


其中location的类型是几何(Point,3785),并且longitudelatituderadius是浮点型(例如-100、44、30,表示100W / 44N / 30“单位”-参见下文)

请参阅什么是在a中查找所有对象的最佳方法另一个物体的半径?在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有什么区别?

–已调整
16年1月12日在17:35



他们是不同的预测。 3875与3857-我不知道一个人是否比另一个人更好

– AlexChaffee
16年1月13日在18:58

“不建议使用EPSG 3785,而采用其他相同的EPSG 3857”-github.com/rgeo/rgeo/pull/61

–雅林
17年1月25日在22:19

#3 楼

听起来好像要将几何存储在几何列中,而不是在地理列中。
很好,但是功能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时。

–文斯
17年7月11日在1:49

#4 楼

我认为这应该可行:

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


评论


如果您将the_geom投放到应该有效的地理位置。 st_dwithin(geography(the_geom),geography(),30000)

– cavila
2015年9月23日下午21:11