Cur*_*per 8 sql sql-server floating-point geometry geography
我有一条@a与另一条线相交的线@b.当我取交点并检测它是否/在哪里与@b相交时,它返回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)
Run Code Online (Sandbox Code Playgroud)
它归结为在计算中处理浮点数时应该使用的一般方法.您不应该使用与浮点数相等的比较if a == b,但总是将它们与您的应用程序域中有意义的某些epsilon精度进行比较,例如if abs(a-b) < 1e-8.
它在概念上类似于执行一些非平凡的计算,例如:
double a = 2.0;
a = sqrt(a);
a = a*a;
Run Code Online (Sandbox Code Playgroud)
然后期望这if a == 2.0将返回真实而不是写作if abs(a-2.0) < 1e-8.
SQL Server中的几何点表示为浮点数,这些数字并不精确.
DECLARE @intersectionPoint geometry = @a.STIntersection(@b)
Run Code Online (Sandbox Code Playgroud)
计算交叉点的最佳精度,但它永远不会精确.
因此,表达式@b.STIntersects(@intersectionPoint)在概念上等同于等式比较.它相当于if @b.STDistance(@intersectionPoint) == 0,只有少数特殊情况才会成立.
你应该使用类似的东西@b.STDistance(@intersectionPoint) < 1e-8.
| 归档时间: |
|
| 查看次数: |
154 次 |
| 最近记录: |