Результат STIntersection: STIntersects = 0

У меня есть линия @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)
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
8
0
280
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Похоже, это ошибка округления. Если я добавлю в ваш код следующее:

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.

Другие вопросы по теме