postgis:ST_LineLocatePoint 中返回的点无法在 ST_Contains 中检测到
postgis: point returned in ST_LineLocatePoint not able to detect in ST_Contains
我正在使用 postgis
的 ST_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_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表示该点在直线的很小距离内,所以有效包含了该点。
我正在使用 postgis
的 ST_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_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表示该点在直线的很小距离内,所以有效包含了该点。