postgis:ST_LineLocatePoint 中返回的点无法在 ST_Contains 中检测到

postgis: point returned in ST_LineLocatePoint not able to detect in ST_Contains

我正在使用 postgisST_LineLocatePoint 找出 LineString 上最接近给定 Point 的点,并使用 ST_LineInterpolatePoint 来从 returned 浮点数中提取 Point

ST_LineLocatePoint 查询:

SELECT ST_AsText(ST_LineInterpolatePoint(foo.the_line,
         ST_LineLocatePoint(foo.the_line,
           ST_GeomFromText('POINT(12.962315 77.584841)')))) AS g
FROM (
  SELECT ST_GeomFromText('LINESTRING(12.96145 77.58408,12.96219 77.58447,12.96302 77.58489,
                          12.96316 77.58496,12.96348 77.58511)') AS the_line
) AS foo;

输出:

                    g                     
------------------------------------------
 POINT(12.9624389808159 77.5845959902924)

这正是我通过的linestring。显示演示 here.

但是当我使用 ST_Contains 检查这个 point 是否位于 linestring 中时,它总是 return false,即使点位于其中。

ST_Contains 查询:

SELECT ST_Contains(ST_GeomFromText('LINESTRING(12.96145 77.58408,12.96219 77.58447,
         12.96302 77.58489, 12.96316 77.58496, 12.96348 77.58511)'),
           ST_GeomFromText('POINT(12.9624389808159 77.5845959902924)'));

输出

 st_contains 
-------------
 f

我没有找到我做错的地方。谁能帮我解决这个问题。

Postgresql : 9.4
postgis : 2.1

参考:ST_LineLocatePoint, ST_Contains

ST_Contains() 只有 returns true 如果要测试的 geometry 位于提供的 geometry 内。在你的情况下,point 必须位于 linestring 并且这始终是 false,因为 linestring 没有内部.

您应该改用 ST_Covers() 函数:true 如果 geometry 没有要测试的点(您的 point)位于 之外 提供的 geometry(你的 linestring)。

I am not getting where I am doing wrong.

我觉得你做的很好...我前段时间遇到了同样的问题...我使用ST_ClosestPoint在线串上定位点然后用这个点切割线串,但我可以't。

遵循文档:

ST_ClosestPoint — Returns the 2-dimensional point on g1 that is closest to g2. This is the first point of the shortest line.

所以我遇到这样的情况,一个函数说 - 这个点在一条线上,而其他函数说 - 好的,但我不能切,因为你的点不在一条线上......我和你一样困惑现在...

在我的例子中,解决方案是绘制另一条线,该线将在给定点与第一条线 'exactly' 相交,然后第一条线被切割...

经过一些研究,我发现问题是关于计算和写入的坐标的舍入。我向自己解释说,根据定义,线是无限细的,点是无限小的(它们没有面积),所以它们很容易错过彼此——但这是我的推理,我不确定它是否是好的。我建议您使用 st_intersects,但 st_buffer 或 ST_DWithin 函数非常低,距离也非常短。

要确保您的点位于一条线上,它必须是这条线的一部分(例如 LINESTRING(0 0, 5 5) 点 (0 0) 和 (5 5)。点 (3) 的示例3) 有效,因为它的坐标是在没有任何舍入的情况下计算的。

这实际上是一个非常常见的问题(很可能是重复的,但我懒得找了。)

此问题与数值精度有关,其中 Point 不完全 位于 LineString 上,但与它的距离非常小。有点像 SELECT sin(pi()) 不完全为零。

与其使用通常需要精确点头的 DE-9IM spatial predicates(如包含或覆盖等),不如使用基于距离的技术(例如具有较小距离阈值的 ST_DWithin)更稳健.例如:

SELECT ST_Distance(the_point, the_line),
  ST_Covers(the_point, the_line),
  ST_DWithin(the_point, the_line, 1e-10)
FROM (
  SELECT 'POINT(12.9624389808159 77.5845959902924)'::geometry AS the_point,
    'LINESTRING(12.96145 77.58408,12.96219 77.58447,12.96302 77.58489,12.96316 77.58496,12.96348 77.58511)'::geometry AS the_line
) AS foo;
-[ RECORD 1 ]----------------------
st_distance | 1.58882185807825e-014
st_covers   | f
st_dwithin  | t

这里可以看到ST_DWithin表示该点在直线的很小距离内,所以有效包含了该点。