11. Просторові відносини

До цього часу ми використовували лише просторові функції, які вимірюють (ST_Area, ST_Length), серіалізують (ST_GeomFromText) або десеріалізують (ST_AsGML) геометрії. Спільним для цих функцій є те, що вони працюють лише з однією геометрією за раз.

Просторові бази даних є потужними, оскільки вони не тільки зберігають геометрію, але й мають можливість порівнювати відносини між геометріями.

На такі питання, як «Де найближчі велосипедні стоянки до парку?» або «Де перетинаються лінії метро та вулиці?», можна відповісти лише порівнявши геометрію велосипедних стійок, вулиць та ліній метро.

Стандарт OGC визначає наступний набір методів для порівняння геометрій.

11.1. ST_Equals

:command:`ST_Equals(geometry A, geometry B)`перевіряє просторову рівність двох геометрій.

_images/st_equals.png

ST_Equals повертає TRUE, якщо дві геометрії одного типу мають однакові значення координат x, y, тобто якщо друга фігура дорівнює (ідентична) першій фігурі.

Спочатку витягнемо представлення точки з таблиці nyc_subway_stations. Візьмемо тільки запис для “Broad St”.

SELECT name, geom
FROM nyc_subway_stations
WHERE name = 'Broad St';
   name   |                      geom
----------+---------------------------------------------------
 Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141

Потім додайте геометричне представлення назад у ST_Equals:

SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(
  geom,
  '0101000020266900000EEBD4CF27CF2141BC17D69516315141');
Broad St

Примітка

Представлення точки не було дуже зрозумілим для людини (0101000020266900000EEBD4CF27CF2141BC17D69516315141), але це було точне представлення значень координат. Для тесту на рівність необхідно використовувати точні координати.

11.2. ST_Intersects, ST_Disjoint, ST_Crosses and ST_Overlaps

ST_Intersects, ST_Crosses, та ST_Overlaps перевірити, чи перетинаються внутрішні частини геометрій.

_images/st_intersects.png

ST_Intersects(geometry A, geometry B) повертає t (TRUE), якщо дві фігури мають спільний простір, тобто якщо їхні межі або внутрішні частини перетинаються.

_images/st_disjoint.png

Протилежністю ST_Intersects є ST_Disjoint(geometry A , geometry B). Якщо дві геометрії є роз’єднаними, вони не перетинаються, і навпаки. Насправді, часто ефективніше перевіряти «не перетинається», ніж «роз’єднане», оскільки перевірки перетину можуть бути індексовані просторово, а перевірки роз’єднання — ні.

_images/st_crosses.png

Для порівняння багатоточкового/багатокутного, багатоточкового/лінійного, лінійного/лінійного, лінійного/багатокутного та лінійного/багатокутного: ST_Crosses(geometry A, geometry B) повертає t (TRUE), якщо перетин дає геометрію, розмір якої на один менше, ніж максимальний розмір двох вихідних геометрій, а множина перетину знаходиться всередині обох вихідних геометрій.

_images/st_overlaps.png

:команда:`ST_Overlaps(geometry A, geometry B)` порівнює дві геометрії однакового розміру і повертає TRUE, якщо їх перетин дає геометрію, відмінну від обох, але однакового розміру.

Візьмемо станцію метро Broad Street і визначимо її околиці за допомогою функції ST_Intersects:

SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = 'Broad St';
POINT(583571 4506714)
SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(geom, ST_GeomFromText('POINT(583571 4506714)',26918));
        name        | boroname
--------------------+-----------
 Financial District | Manhattan

11.3. ST_Touches

ST_Touches перевіряє, чи дві геометрії стикаються на своїх межах, але не перетинаються всередині

_images/st_touches.png

:команда:`ST_Touches(geometry A, geometry B)` повертає TRUE, якщо межі будь-якої з геометрій перетинаються або якщо тільки одна з внутрішніх частин геометрії перетинається з межею іншої.

11.4. ST_Within та ST_Contains

ST_Within та ST_Contains перевіряють, чи одна геометрія повністю знаходиться всередині іншої.

_images/st_within.png

:команда:`ST_Within(геометрія A , геометрія B)` повертає TRUE, якщо перша геометрія повністю знаходиться всередині другої геометрії. ST_Within перевіряє результат, який є точно протилежним до ST_Contains.

:команда:`ST_Contains(geometry A, geometry B)` повертає TRUE, якщо друга геометрія повністю міститься в першій геометрії.

11.5. ST_Distance та ST_DWithin

Дуже поширеним питанням у сфері ГІС є «знайти всі об’єкти, що знаходяться на відстані X від цього об’єкта».

Команда ST_Distance(geometry A, geometry B) обчислює найкоротшу відстань між двома геометріями та повертає її у вигляді числа з плаваючою комою. Це корисно для фактичного повідомлення про відстань між об’єктами.

SELECT ST_Distance(
  ST_GeometryFromText('POINT(0 5)'),
  ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
3

Для перевірки, чи два об’єкти знаходяться на відстані один від одного, функція ST_DWithin надає індексоване прискорення перевірки true/false. Це корисно для таких питань, як «скільки дерев знаходиться в межах 500 метрів від дороги?». Вам не потрібно обчислювати фактичний буфер, достатньо перевірити відношення відстаней.

_images/st_dwithin.png

Знову скориставшись станцією метро Broad Street, ми можемо знайти вулиці поблизу (в радіусі 10 метрів) від станції метро:

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
        geom,
        ST_GeomFromText('POINT(583571 4506714)',26918),
        10
      );
     name
--------------
   Wall St
   Broad St
   Nassau St

І ми можемо перевірити відповідь на карті. Станція Broad St насправді знаходиться на перетині вулиць Wall, Broad і Nassau.

_images/broad_st.jpg

11.6. Список функцій

ST_Contains(geometry A, geometry B): Повертає true, якщо і тільки якщо жодна точка B не лежить зовні A, і принаймні одна точка всередині B лежить всередині A.

ST_Crosses(geometry A, geometry B): Повертає TRUE, якщо надані геометрії мають деякі, але не всі внутрішні точки спільні.

ST_Disjoint(geometry A , geometry B): Повертає TRUE, якщо геометрії не «перетинаються в просторі» — якщо вони не мають спільного простору.

ST_Distance(geometry A, geometry B): Повертає двовимірну декартову мінімальну відстань (на основі просторової референції) між двома геометріями в проекційних одиницях.

ST_DWithin(geometry A, geometry B, radius): Повертає true, якщо геометрії знаходяться на відстані (радіусі) одна від одної, що не перевищує задане значення.

ST_Equals(geometry A, geometry B): Повертає true, якщо задані геометрії представляють одну і ту ж геометрію. Напрямок ігнорується.

ST_Intersects(geometry A, geometry B): Повертає TRUE, якщо геометрії/географія «просторово перетинаються» (мають спільну частину простору), і FALSE, якщо вони не перетинаються (вони роз’єднані).

ST_Overlaps(geometry A, geometry B): Повертає TRUE, якщо геометрії мають спільний простір, мають однаковий розмір, але не повністю містяться одна в одній.

ST_Touches(geometry A, geometry B): Повертає TRUE, якщо геометрії мають принаймні одну спільну точку, але їхні внутрішні частини не перетинаються.

ST_Within(geometry A , geometry B): Повертає true, якщо геометрія A повністю знаходиться всередині геометрії B