11. Просторові відносини¶
До цього часу ми використовували лише просторові функції, які вимірюють (ST_Area, ST_Length), серіалізують (ST_GeomFromText) або десеріалізують (ST_AsGML) геометрії. Спільним для цих функцій є те, що вони працюють лише з однією геометрією за раз.
Просторові бази даних є потужними, оскільки вони не тільки зберігають геометрію, але й мають можливість порівнювати відносини між геометріями.
На такі питання, як «Де найближчі велосипедні стоянки до парку?» або «Де перетинаються лінії метро та вулиці?», можна відповісти лише порівнявши геометрію велосипедних стійок, вулиць та ліній метро.
Стандарт OGC визначає наступний набір методів для порівняння геометрій.
11.1. ST_Equals¶
:command:`ST_Equals(geometry A, geometry B)`перевіряє просторову рівність двох геометрій.

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 перевірити, чи перетинаються внутрішні частини геометрій.

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

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

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

:команда:`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 перевіряє, чи дві геометрії стикаються на своїх межах, але не перетинаються всередині

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

:команда:`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 метрів від дороги?». Вам не потрібно обчислювати фактичний буфер, достатньо перевірити відношення відстаней.

Знову скориставшись станцією метро 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.

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