У меня есть линия @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)


Похоже, это ошибка округления. Если я добавлю в ваш код следующее:
SELECT @b.STDistance(@intersectionPoint);
Получаю ≈ 3 фемтометра. Что, если вы не измеряете что-то в атомном масштабе, вероятно, достаточно хорошо, чтобы его можно было рассматривать как «на грани».
Из любопытства, какую проблему вы пытаетесь решить?
Это сводится к общему подходу, который вы должны использовать при работе с числами с плавающей запятой в вычислениях. Вы не должны использовать сравнение на равенство с числами с плавающей запятой, такими как if a == b, но всегда сравнивайте их с некоторой точностью эпсилон, которая имеет смысл в вашем домене приложения, например if abs(a-b) < 1e-8.
Концептуально это похоже на выполнение некоторых нетривиальных вычислений, например:
double a = 2.0;
a = sqrt(a);
a = a*a;
а затем ожидая, что if a == 2.0 вернет true вместо записи if abs(a-2.0) < 1e-8.
Геометрическая точка в SQL Server представлена числами с плавающей запятой, которые не являются точными.
DECLARE @intersectionPoint geometry = @a.STIntersection(@b)
вычисляет точку пересечения с максимальной точностью, но никогда не будет точным.
Таким образом, выражение типа @b.STIntersects(@intersectionPoint) концептуально эквивалентно сравнению с равенством. Он эквивалентен if @b.STDistance(@intersectionPoint) == 0, что верно только в некоторых особых случаях.
Вместо этого вы должны использовать что-то вроде @b.STDistance(@intersectionPoint) < 1e-8.