Вопрос или проблема
Я вижу запутанные результаты при использовании ST_Intersection с типами географии. Например, этот запрос
select
st_astext(
st_intersection(
ST_GeographyFromText('LINESTRING(-40 40, 40 40)'),
ST_GeographyFromText('LINESTRING(0 30, 0 50)')
))
возвращает POINT(0 40)
. Это то, что я ожидал от пересечения объектов геометрии. Поскольку линии должны интерпретироваться как вдоль больших кругов в типе географии, я ожидал, что пересечение будет примерно POINT(0 47.6)
.
Что еще более запутанно, так это то, что запрос
select
st_intersects(
ST_GeographyFromText('LINESTRING(-40 40, 40 40)'),
ST_GeographyFromText('LINESTRING(0 39, 0 41)')
)
на самом деле возвращает false. Я что-то упускаю или функция ST_INTERSECTION не работает должным образом для типов географии?
Как указал @Damien_The_Unbeliever, функция ST_INTERSECTION является всего лишь тонкой оболочкой над функцией на основе геометрии и не выполняет никаких сферических расчетов. Если вы хотите получить (приблизительный) правильный результат, вы можете сначала сегментировать географию (которая выполняет сферические расчеты), как показано ниже
select
st_astext(
st_intersection(
ST_Segmentize(ST_GeographyFromText('LINESTRING(-40 40, 40 40)'), 1000),
ST_Segmentize(ST_GeographyFromText('LINESTRING(0 30, 0 50)'), 1000)
))
Это возвращает POINT(0 47.60591395513534)
как и ожидалось.
Ответ или решение
Когда вы работаете с типами данных geography в PostGIS, особенно с функциями ST_Intersection и ST_Intersects, важно понимать, как они обрабатывают геометрические данные и какие особенности могут вызывать путаницу.
Проблема: ST_Intersection и ST_Intersects с типами geography
При выполнении вашего запроса с использованием ST_Intersection для строковых линий, представленных как Geography типы, вы ожидаете получить результат, основанный на расчетах по сфере. Однако, как вы заметили, функция возвращает результат, как если бы использовались типы Geometry, что приводит к недоразумениям.
Пример
Ваш первоначальный запрос возвращает POINT(0 40)
. Это поведение объясняется тем, что ST_Intersection на самом деле является оберткой для функции, работающей с типами Geometry. В результате, она не учитывает сферические вычисления, что является критичным для работы с типами Geography.
Кроме того, когда вы используете ST_Intersects с линиями, которые должны пересекаться, вы получаете неверный результат (false). Это также связано с тем, что функция не учитывает сферическое представление данных и проводит проверку без соответствующей сегментации.
Решение: Использование ST_Segmentize
Чтобы избежать этих проблем и получить корректный результат для типов geography, вы можете использовать функцию ST_Segmentize. Эта функция разбивает географические линии на более мелкие отрезки, производя необходимые сферические вычисления и, таким образом, предоставляя более точные результаты.
Пример корректного запроса
Ниже приведен пример, который показывает, как правильно использовать ST_Segmentize вместе с ST_Intersection:
SELECT
ST_AsText(
ST_Intersection(
ST_Segmentize(ST_GeographyFromText('LINESTRING(-40 40, 40 40)'), 1000),
ST_Segmentize(ST_GeographyFromText('LINESTRING(0 30, 0 50)'), 1000)
)
);
Этот запрос вернет POINT(0 47.60591395513534)
, что соответствует вашим ожиданиям и отражает действительное пересечение на сферической поверхности.
Заключение
Таким образом, чтобы правильно работать с пересечениями и отношениями между географическими объектами в PostGIS, важно учитывать особенности использования функций для типов geography. Использование функции ST_Segmentize перед вычислением пересечений или проверкой на пересечение — это ключ к получению корректных результатов, соответствующих вашим ожиданиям в контексте работы на сфере.
Если вы столкнетесь с дальнейшими затруднениями, рекомендуется всегда проверять документацию PostGIS или сообщество, которое активно обсуждает подобные темы.