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

时间:2015-09-29 15:03:23

标签: postgresql gis postgis

我正在使用postgis' ST_LineLocatePoint找出LineString与给定Point的最近点,并使用ST_LineInterpolatePoint从返回的浮点数中提取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

但是当我检查point linestring是否位于使用ST_Contains的{​​{1}}时,它始终会返回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_LineLocatePointST_Contains

3 个答案:

答案 0 :(得分:2)

  

我没有得到我做错的地方。

我觉得你做得很好......前段时间我遇到了同样的问题......我用ST_ClosestPoint来定位线串上的点,然后用这一点剪切一个线串,但我可以& #39;吨。

遵循文件:

  

ST_ClosestPoint - 返回g1上的二维点   最接近g2。这是最短线的第一点。

所以我得到一个函数说的情况 - 这一点在一条线上,其他函数说 - 好的,但是我不能削减因为你的观点不在线......我很困惑你和我一样#39;现在......

在我的情况下,分辨率是绘制另一条线,它将与第一条线完全相交。在给定的点上,在第一行被切断后......

经过一番研究后,我发现问题是关于计算和写入的坐标的舍入。我向自己解释说,根据定义,线条是无限薄的,点是无限小的(它们没有区域),所以它们很容易错过对方 - 但它是我的推理,而且我'我不确定它是否好。我建议你使用st_intersects,但st_buffer或ST_DWithin功能非常低,距离也很短。

为了确保你的点位于一条线上,它必须是该线的一部分(例如LINESTRING(0 0,5 5)点(0 0)和(5 5)。点(3 3)示例因为它的坐标在没有任何舍入的情况下计算,所以可以正常工作。

答案 1 :(得分:1)

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

问题与数值精度有关,其中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表示该点在该行的一个非常小的距离内,因此它实际上包含该点。

答案 2 :(得分:0)

如果要测试的ST_Contains()位于提供的true内,则

geometry仅返回geometry。在您的情况下,point必须在<{>} <{1}}内,这始终为linestring,因为false没有内部。

如果linestring无法测试(ST_Covers()之外,则应使用true函数:geometry提供point(您的geometry)。