STIntersection 结果为 STIntersects = 0

STIntersection result is STIntersects = 0

我有一条线 @a 与另一条线 @b 相交。当我取交点并检测到 if/where 它与 @b 相交时,它 returns false

declare @a GEOMETRY = Geometry::STGeomFromText('LINESTRING (-83 24, -80.4907132243685 24.788632986627039)', 4326)
declare @b GEOMETRY = Geometry::STGeomFromText('LINESTRING (-74.7 21.8, -75.7 22.1, -77.8 22.6, -79.4 23.3, -80.4 24.5, -81.5 28, -84 33, -87 36)', 4326)


DECLARE @intersectionPoint geometry = @a.STIntersection(@b) -- POINT (-80.49071322436852 24.788632986627078)

IF @intersectionPoint IS NULL
    THROW 50000, '@intersectionPoint not found', 1


-- Expect 1, Result 0
SELECT @b.STIntersects(@intersectionPoint)

这似乎是一个舍入错误。如果我将以下内容添加到您的代码中:

SELECT @b.STDistance(@intersectionPoint);

我得到 ≈ 3 个飞米计。除非你在原子尺度上测量某些东西,否则它可能足以被视为 "on the line"。

出于好奇,你到底想解决什么问题?

它归结为在计算中处理浮点数时应该使用的一般方法。您不应该对浮点数进行相等比较,例如 if a == b,而应始终将它们与在您的应用程序域中有意义的一些 epsilon 精度进行比较,例如 if abs(a-b) < 1e-8.

它在概念上类似于执行一些非平凡的计算,例如:

double a = 2.0;
a = sqrt(a);
a = a*a;

然后期望 if a == 2.0 会 return 为真而不是写 if abs(a-2.0) < 1e-8.


SQL服务器中的几何点表示为浮点数,不精确。

DECLARE @intersectionPoint geometry = @a.STIntersection(@b)

以最佳精度计算交点,但永远不会准确。

所以,像@b.STIntersects(@intersectionPoint)这样的表达式在概念上等同于相等比较。它等同于 if @b.STDistance(@intersectionPoint) == 0,仅在少数特殊情况下才成立。

您应该改用 @b.STDistance(@intersectionPoint) < 1e-8 之类的东西。