9.11. Геометрические функции и операторы

Для геометрических типов point, box, lseg, line, path, polygon и circle разработан большой набор встроенных функций и операторов, представленный в Табл. 9-31, Табл. 9-32 и Табл. 9-33.

Предостережение

Заметьте, что оператор "идентичности", ~=, представляет обычное сравнение на равенство значений point, box, polygon и circle. Для некоторых из этих типов определён также оператор =, но = проверяет только равенство площадей. Другие скалярные операторы сравнения (<= и т. д.) так же сравнивают площади значений этих типов.

Таблица 9-31. Геометрические операторы

ОператорОписаниеПример
+ Сдвиг box '((0,0),(1,1))' + point '(2.0,0)'
- Сдвиг box '((0,0),(1,1))' - point '(2.0,0)'
* Масштабирование/поворот box '((0,0),(1,1))' * point '(2.0,0)'
/ Масштабирование/поворот box '((0,0),(2,2))' / point '(2.0,0)'
# Точка или прямоугольник в пересечении box '((1,-1),(-1,1))' # box '((1,1),(-2,-2))'
# Число точек в пути или вершин в многоугольнике # path '((1,0),(0,1),(-1,0))'
@-@ Длина, периметр или длина окружности @-@ path '((0,0),(1,0))'
@@ Центр @@ circle '((0,0),10)'
## Точка, ближайшая к первому операнду и принадлежащая второму point '(0,0)' ## lseg '((2,0),(0,2))'
<-> Расстояние между операндами circle '((0,0),1)' <-> circle '((5,0),1)'
&& Пересекаются ли операнды? (Для положительного ответа достаточно одной общей точки.) box '((0,0),(1,1))' && box '((0,0),(2,2))'
<< Строго слева? circle '((0,0),1)' << circle '((5,0),1)'
>> Строго справа? circle '((5,0),1)' >> circle '((0,0),1)'
&< Не простирается правее? box '((0,0),(1,1))' &< box '((0,0),(2,2))'
&> Не простирается левее? box '((0,0),(3,3))' &> box '((0,0),(2,2))'
<<| Строго ниже? box '((0,0),(3,3))' <<| box '((3,4),(5,5))'
|>> Строго выше? box '((3,4),(5,5))' |>> box '((0,0),(3,3))'
&<| Не простирается выше? box '((0,0),(1,1))' &<| box '((0,0),(2,2))'
|&> Не простирается ниже? box '((0,0),(3,3))' |&> box '((0,0),(2,2))'
<^ Ниже (может касаться)? circle '((0,0),1)' <^ circle '((0,5),1)'
>^ Выше (может касаться)? circle '((0,5),1)' >^ circle '((0,0),1)'
?# Пересекает? lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))'
?- Горизонтальный объект? ?- lseg '((-1,0),(1,0))'
?- Выровнены по горизонтали? point '(1,0)' ?- point '(0,0)'
?| Вертикальный объект? ?| lseg '((-1,0),(1,0))'
?| Выровнены по вертикали? point '(0,1)' ?| point '(0,0)'
?-| Перпендикулярны? lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))'
?|| Параллельны? lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))'
@> Первый объект включает второй? circle '((0,0),2)' @> point '(1,1)'
<@ Первый объект включён во второй? point '(1,1)' <@ circle '((0,0),2)'
~= Одинаковы? polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))'

Замечание: До PostgreSQL 8.2 операторы включения @> и <@ назывались соответственно ~ и @. Эти имена по-прежнему доступны, но считаются устаревшими и в конце концов будут удалены.

Таблица 9-32. Геометрические функции

ФункцияТип результатаОписаниеПример
area(объект) double precision площадь area(box '((0,0),(1,1))')
center(объект) point центр center(box '((0,0),(1,2))')
diameter(circle) double precision диаметр круга diameter(circle '((0,0),2.0)')
height(box) double precision вертикальный размер прямоугольника height(box '((0,0),(1,1))')
isclosed(path) boolean замкнутый путь? isclosed(path '((0,0),(1,1),(2,0))')
isopen(path) boolean открытый путь? isopen(path '[(0,0),(1,1),(2,0)]')
length(объект) double precision длина length(path '((-1,0),(1,0))')
npoints(path) int число точек npoints(path '[(0,0),(1,1),(2,0)]')
npoints(polygon) int число точек npoints(polygon '((1,1),(0,0))')
pclose(path) path преобразует путь в замкнутый pclose(path '[(0,0),(1,1),(2,0)]')
popen(path) path преобразует путь в открытый popen(path '((0,0),(1,1),(2,0))')
radius(circle) double precision радиус окружности radius(circle '((0,0),2.0)')
width(box) double precision горизонтальный размер прямоугольника width(box '((0,0),(1,1))')

Таблица 9-33. Функции преобразования геометрических типов

ФункцияТип результатаОписаниеПример
box(circle) box окружность в прямоугольник box(circle '((0,0),2.0)')
box(point) box точка в пустой прямоугольник box(point '(0,0)')
box(point, point) box точки в прямоугольник box(point '(0,0)', point '(1,1)')
box(polygon) box многоугольник в прямоугольник box(polygon '((0,0),(1,1),(2,0))')
bound_box(box, box) box прямоугольники в окружающий прямоугольник bound_box(box '((0,0),(1,1))', box '((3,3),(4,4))')
circle(box) circle прямоугольник в окружность circle(box '((0,0),(1,1))')
circle(point, double precision) circle окружность из центра и радиуса circle(point '(0,0)', 2.0)
circle(polygon) circle многоугольник в окружность circle(polygon '((0,0),(1,1),(2,0))')
line(point, point) line точки в прямую line(point '(-1,0)', point '(1,0)')
lseg(box) lseg диагональ прямоугольника в отрезок lseg(box '((-1,0),(1,0))')
lseg(point, point) lseg точки в отрезок lseg(point '(-1,0)', point '(1,0)')
path(polygon) path многоугольник в путь path(polygon '((0,0),(1,1),(2,0))')
point(double precision, double precision) point образует точку point(23.4, -44.5)
point(box) point центр прямоугольника point(box '((-1,0),(1,0))')
point(circle) point центр окружности point(circle '((0,0),2.0)')
point(lseg) point центр отрезка point(lseg '((-1,0),(1,0))')
point(polygon) point центр многоугольника point(polygon '((0,0),(1,1),(2,0))')
polygon(box) polygon прямоугольник в многоугольник с 4 вершинами polygon(box '((0,0),(1,1))')
polygon(circle) polygon круг в многоугольник с 12 вершинами polygon(circle '((0,0),2.0)')
polygon(число_точек, circle) polygon окружность с заданным числом_точек polygon(12, circle '((0,0),2.0)')
polygon(path) polygon путь в многоугольник polygon(path '((0,0),(1,1),(2,0))')

К двум компонентам типа point (точка) можно обратиться, как к элементам массива с индексами 0 и 1. Например, если t.p — столбец типа point, SELECT p[0] FROM t вернёт координату X, а UPDATE t SET p[1] = ... изменит координату Y. Таким же образом, значение типа box или lseg можно воспринимать как массив двух значений типа point.

Функция area работает с типами box, circle и path. При этом для типа path заданный путь не должен быть самопересекающимся. Например, эта функция не примет значение типа path '((0,0),(0,1),(2,1),(2,2),(1,2),(1,0),(0,0))'::PATH, но примет визуально идентичный путь '((0,0),(0,1),(1,1),(1,2),(2,2),(2,1),(1,1),(1,0),(0,0))'::PATH. Если вы не вполне поняли, что здесь подразумевается под самопересечением пути, нарисуйте на бумаге две фигуры по приведённым координатам.