python 中 PostGIS 的 ST_DWithin 替代方案 shapely

Alternative of ST_DWithin of PostGIS in python shapely

我有两个线串 Line1、Line2。

line1 = "LINESTRING(72.863221 18.782499,72.863736 18.770147,72.882275 18.756169,72.881417 18.750805,72.878842 18.736987,72.874379 18.709512,72.860989 18.679593,72.864422 18.653897)"
line2 = "LINESTRING(72.883133 18.780793,72.882103 18.760314,72.862534 18.716422,72.860474 18.683577)"

我正在尝试以匀称的方式执行以下 POSTGIS 查询。到目前为止,我还没有找到 ST_DWithin 命令的替代方法。

road2 = "ST_GeographyFromText('SRID=4326;%s')"%line1
road4 = "ST_GeographyFromText('SRID=4326;%s')"%line2
cur.execute("SELECT ST_AsText(road1) from %s as road1,%s as road2 
            where ST_DWithin(road1,road2,500)"%(road2,road4))
res = cur.fetchall()
print res

有谁知道 ST_DWithin 在 shapely 中的替代方法是什么?

据我所知,shapely只支持平面坐标系的操作(不支持地理类型)。然而,对于不太大以至于可以忽略地球曲率的 LineStrings,可以部分地 "circumvent" 通过:

  • 在某些平面投影中工作(例如直接在 lat/lon 或 lon/lat 坐标中)

  • ST_DWithin and the first note in the documentation of ST_Expand 的文档中的第二个注释之后,即:

    1. 检查第二个 LineString 的边界框是否与第一个 LineString 的扩展边界框相交
    2. 如果是,检查最小距离是否确实低于规定的阈值

例如:

from shapely.wkt import dumps, loads
from shapely.geometry.geo import box

spec = [
    "LINESTRING(72.863221 18.782499,72.863736 18.770147,72.882275 18.756169,72.881417 18.750805,72.878842 18.736987,72.874379 18.709512,72.860989 18.679593,72.864422 18.653897)",
    "LINESTRING(72.883133 18.780793,72.882103 18.760314,72.862534 18.716422,72.860474 18.683577)"
]

lines = list(map(loads, spec))

eta = 0.005

b1 = box(*lines[0].bounds).buffer(eta)
b2 = box(*lines[1].bounds)

flag = b2.intersects(b1) and (lines[0].distance(lines[1]) < eta)
print(eta, flag)

或者,如果您想检查整个第二个 LineString 是否在第一个 LineString 的规定阈值内,您也可以使用 buffer 方法:

lines[0].buffer(eta).contains(lines[1])

此处提供给 buffer 方法的阈值在定义 LineStrings 的同一坐标系中表示。在 lon/lat 系统中,这将代表 "central angle" - 那么问题在于 great circle distance corresponding to a fixed eta not only depends on the particular values of latitude and longitude but also on the direction of the displacement. However, if the LineStrings are not too large and the required precision is not too high, it probably won't matter that much.