【问题标题】:postgis: point returned in ST_LineLocatePoint not able to detect in ST_Containspostgis:在 ST_LineLocatePoint 中返回的点无法在 ST_Contains 中检测到
【发布时间】:2015-09-29 15:03:23
【问题描述】:

我正在使用postgisST_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

但是当我使用ST_Contains检查这个point是否在linestring中时,它总是返回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

【问题讨论】:

    标签: postgresql gis postgis


    【解决方案1】:

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

    我认为你做得很好......我前段时间遇到了同样的问题......我使用ST_ClosestPoint 定位线串上的点,然后用这个点切割线串,但我不能。

    按照文档:

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

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

    在我的情况下,解决方案是绘制另一条线,该线将在给定点“完全”与第一条线相交,并且在第一条线被切割之后......

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

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

    【讨论】:

      【解决方案2】:

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

      这个问题与数值精度有关,Point 不是 完全 位于 LineString 上,而是在它的一个非常小的距离内。有点像SELECT sin(pi()) 不完全为零。

      与使用通常期望精确点头的DE-9IM spatial predicates(如 Contains 或 Covers 等)相比,使用 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表示该点在直线的一个很小的距离内,因此它有效地包含了该点。

      【讨论】:

        【解决方案3】:

        ST_Contains() 仅在要测试的geometry 位于提供的geometry 范围内时才返回true。在您的情况下,point 必须位于linestring 中,并且这始终是false,因为linestring 没有内部。

        您应该使用ST_Covers() 函数代替:true 如果要测试的geometry(您的point)位于外部提供的geometry(您的@987654334 @)。

        【讨论】:

        • 不考虑您的“linestring 没有内部,因此它总是返回 false”语句,请检查以下返回 true 的查询,并将 linstringpoint 作为输入。 SELECT ST_Contains(ST_GeomFromText('LINESTRING(0 0, 5 5)'),ST_GeomFromText('POINT(3 3)'));
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-16
        相关资源
        最近更新 更多