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

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

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

Оператор

Описание

Пример(ы)

геометрический_тип + pointгеометрический_тип

Добавляет координаты второго аргумента типа point к каждой точке первого аргумента, осуществляя таким образом перенос объекта. Имеется для типов point, box, path и circle.

box '(1,1),(0,0)' + point '(2,0)'(3,1),(2,0)

path + pathpath

Соединяет два открытых пути (если один из путей замкнутый, возвращает NULL).

path '[(0,0),(1,1)]' + path '[(2,2),(3,3),(4,4)]'[(0,0),(1,1),(2,2),(3,3),(4,4)]

геометрический_тип - pointгеометрический_тип

Вычитает координаты второго аргумента типа point из каждой точки первого аргумента, осуществляя таким образом перенос объекта. Имеется для типов point, box, path и circle.

box '(1,1),(0,0)' - point '(2,0)'(-1,1),(-2,0)

геометрический_тип * pointгеометрический_тип

Умножает координаты каждой точки первого аргумента на координаты второго аргумента типа point (координаты точек воспринимаются как комплексные числа с вещественной и мнимой частью, результатом становится их обычное комплексное произведение). Если же рассматривать вторую точку как вектор, данная операция равнозначна умножению размера объекта и расстояния от начала координат на длину вектора с поворотом против часовой стрелки относительно начала координат на угол, равный углу между вектором и осью x. Имеется для типов point, box,[a] path, circle.

path '((0,0),(1,0),(1,1))' * point '(3.0,0)'((0,0),(3,0),(3,3))

path '((0,0),(1,0),(1,1))' * point(cosd(45), sind(45))((0,0),​(0.7071067811865475,0.7071067811865475),​(0,1.414213562373095))

геометрический_тип / pointгеометрический_тип

Делит координаты каждой точки первого аргумента на координаты второго аргумента типа point (координаты точек воспринимаются как комплексные числа с вещественной и мнимой частью, результатом становится их обычное комплексное частное). Если же рассматривать вторую точку как вектор, данная операция равнозначна делению размера объекта и расстояния от начала координат на длину вектора с поворотом по часовой стрелке относительно начала координат на угол, равный углу между вектором и осью x. Имеется для типов point, box,[a] path, circle.

path '((0,0),(1,0),(1,1))' / point '(2.0,0)'((0,0),(0.5,0),(0.5,0.5))

path '((0,0),(1,0),(1,1))' / point(cosd(45), sind(45))((0,0),​(0.7071067811865476,-0.7071067811865476),​(1.4142135623730951,0))

@-@ геометрический_типdouble precision

Вычисляет общую длину. Имеется для типов lseg, path.

@-@ path '[(0,0),(1,0),(1,1)]'2

@@ геометрический_типpoint

Вычисляет центральную точку. Имеется для типов box, lseg, polygon, circle.

@@ box '(2,2),(0,0)'(1,1)

# геометрический_типinteger

Возвращает количество точек. Имеется для типов path, polygon.

# path '((1,0),(0,1),(-1,0))'3

геометрический_тип # геометрический_типpoint

Вычисляет точку пересечения, а если пересечения нет, возвращает NULL. Имеется для типов lseg, line.

lseg '[(0,0),(1,1)]' # lseg '[(1,0),(0,1)]'(0.5,0.5)

box # boxbox

Вычисляет пересечение двух прямоугольников, а если пересечения нет, возвращает NULL.

box '(2,2),(-1,-1)' # box '(1,1),(-2,-2)'(1,1),(-1,-1)

геометрический_тип ## геометрический_типpoint

Вычисляет ближайшую к первому объекту точку, принадлежащую второму объекту. Имеется для следующих пар типов: (point, box), (point, lseg), (point, line), (lseg, box), (lseg, lseg), (line, lseg).

point '(0,0)' ## lseg '[(2,0),(0,2)]'(1,1)

геометрический_тип <-> геометрический_типdouble precision

Вычисляет расстояние между объектами. Имеется для всех семи геометрических типов, для всех сочетаний типа point с другим геометрическим типом, а также для следующих пар типов: (box, lseg), (lseg, line), (polygon, circle) (и пар с обратным порядком).

circle '<(0,0),1>' <-> circle '<(5,0),1>'3

геометрический_тип @> геометрический_типboolean

Первый объект содержит второй? Имеется для следующих пар типов: (box, point), (box, box), (path, point), (polygon, point), (polygon, polygon), (circle, point), (circle, circle).

circle '<(0,0),2>' @> point '(1,1)'t

геометрический_тип <@ геометрический_типboolean

Первый объект содержится во втором? Имеется для следующих пар типов: (point, box), (point, lseg), (point, line), (point, path), (point, polygon), (point, circle), (box, box), (lseg, box), (lseg, line), (polygon, polygon), (circle, circle).

point '(1,1)' <@ circle '<(0,0),2>'t

геометрический_тип && геометрический_типboolean

Объекты пересекаются? (Для выполнения этого условия достаточно одной общей точки.) Имеется для типов box, polygon, circle.

box '(1,1),(0,0)' && box '(2,2),(0,0)'t

геометрический_тип << геометрический_типboolean

Первый объект строго слева от второго? Имеется для типов point, box, polygon, circle.

circle '<(0,0),1>' << circle '<(5,0),1>'t

геометрический_тип >> геометрический_типboolean

Первый объект строго справа от второго? Имеется для типов point, box, polygon, circle.

circle '<(5,0),1>' >> circle '<(0,0),1>'t

геометрический_тип &< геометрический_типboolean

Первый объект не простирается правее второго? Имеется для типов box, polygon, circle.

box '(1,1),(0,0)' &< box '(2,2),(0,0)'t

геометрический_тип &> геометрический_типboolean

Первый объект не простирается левее второго? Имеется для типов box, polygon, circle.

box '(3,3),(0,0)' &> box '(2,2),(0,0)'t

геометрический_тип <<| геометрический_типboolean

Первый объект строго ниже второго? Имеется для типов point, box, polygon, circle.

box '(3,3),(0,0)' <<| box '(5,5),(3,4)'t

геометрический_тип |>> геометрический_типboolean

Первый объект строго выше второго? Имеется для типов point, box, polygon, circle.

box '(5,5),(3,4)' |>> box '(3,3),(0,0)'t

геометрический_тип &<| геометрический_типboolean

Первый объект не простирается выше второго? Имеется для типов box, polygon, circle.

box '(1,1),(0,0)' &<| box '(2,2),(0,0)'t

геометрический_тип |&> геометрический_типboolean

Первый объект не простирается ниже второго? Имеется для типов box, polygon, circle.

box '(3,3),(0,0)' |&> box '(2,2),(0,0)'t

box <^ boxboolean

Первый объект ниже (или касается снизу) второго?

box '((1,1),(0,0))' <^ box '((2,2),(1,1))'t

box >^ boxboolean

Первый объект выше (или касается сверху) второго?

box '((2,2),(1,1))' >^ box '((1,1),(0,0))'t

геометрический_тип ?# геометрический_типboolean

Объекты пересекаются? Имеется для следующих пар типов: (box, box), (lseg, box), (lseg, lseg), (lseg, line), (line, box), (line, line), (path, path).

lseg '[(-1,0),(1,0)]' ?# box '(2,2),(-2,-2)'t

?- lineboolean

?- lsegboolean

Линия является горизонтальной?

?- lseg '[(-1,0),(1,0)]'t

point ?- pointboolean

Точки выровнены по горизонтали (имеют одинаковую координату y)?

point '(1,0)' ?- point '(0,0)'t

?| lineboolean

?| lsegboolean

Линия является вертикальной?

?| lseg '[(-1,0),(1,0)]'f

point ?| pointboolean

Точки выровнены по вертикали (имеют одинаковую координату x)?

point '(0,1)' ?| point '(0,0)'t

line ?-| lineboolean

lseg ?-| lsegboolean

Линии перпендикулярны?

lseg '[(0,0),(0,1)]' ?-| lseg '[(0,0),(1,0)]'t

line ?|| lineboolean

lseg ?|| lsegboolean

Линии параллельны?

lseg '[(-1,0),(1,0)]' ?|| lseg '[(-1,2),(1,2)]'t

геометрический_тип ~= геометрический_типboolean

Объекты совпадают? Имеется для типов point, box, polygon, circle.

polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))'t

[a] При «повороте» прямоугольника эти операторы только перемещают его угловые точки: стороны прямоугольника считаются всегда параллельными осям. Таким образом, эта операция, в отличие от настоящего поворота, изменяет размер прямоугольника.


Внимание

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

Примечание

До Postgres Pro 14 применявшиеся к точкам операторы point <<| point (строго ниже) и point |>> point (строго выше) назывались <^ и >^ соответственно. Эти имена по-прежнему доступны, но считаются устаревшими и в конце концов будут удалены.

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

Функция

Описание

Пример(ы)

area ( геометрический_тип ) → double precision

Вычисляет площадь. Имеется для типов box, path, circle. Путь, переданный в аргументе типа path, должен быть замкнутым; в противном случае возвращается NULL. Если же путь является самопересекающимся, результат может не иметь смысла.

area(box '(2,2),(0,0)')4

center ( geometric_type ) → point

Вычисляет центральную точку. Имеется для типов box, circle.

center(box '(1,2),(0,0)')(0.5,1)

diagonal ( box ) → lseg

Вычисляет диагональ прямоугольника в виде отрезка (аналогично lseg(box)).

diagonal(box '(1,2),(0,0)')[(1,2),(0,0)]

diameter ( circle ) → double precision

Вычисляет диаметр круга.

diameter(circle '<(0,0),2>')4

height ( box ) → double precision

Вычисляет вертикальный размер прямоугольника.

height(box '(1,2),(0,0)')2

isclosed ( path ) → boolean

Путь является замкнутым?

isclosed(path '((0,0),(1,1),(2,0))')t

isopen ( path ) → boolean

Путь является открытым?

isopen(path '[(0,0),(1,1),(2,0)]')t

length ( геометрический_тип ) → double precision

Вычисляет общую длину. Имеется для типов lseg, path.

length(path '((-1,0),(1,0))')4

npoints ( геометрический_тип ) → integer

Возвращает количество точек. Имеется для типов path, polygon.

npoints(path '[(0,0),(1,1),(2,0)]')3

pclose ( path ) → path

Преобразует путь в замкнутый.

pclose(path '[(0,0),(1,1),(2,0)]')((0,0),(1,1),(2,0))

popen ( path ) → path

Преобразует путь в открытый.

popen(path '((0,0),(1,1),(2,0))')[(0,0),(1,1),(2,0)]

radius ( circle ) → double precision

Вычисляет радиус окружности.

radius(circle '<(0,0),2>')2

slope ( point, point ) → double precision

Вычисляет наклон линии, проведённой через две точки.

slope(point '(0,0)', point '(2,1)')0.5

width ( box ) → double precision

Вычисляет горизонтальный размер прямоугольника.

width(box '(1,2),(0,0)')1


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

Функция

Описание

Пример(ы)

box ( circle ) → box

Вычисляет прямоугольник, вписанный в окружность.

box(circle '<(0,0),2>')(1.414213562373095,1.414213562373095),​(-1.414213562373095,-1.414213562373095)

box ( point ) → box

Преобразует точку в пустой прямоугольник.

box(point '(1,0)')(1,0),(1,0)

box ( point, point ) → box

Преобразует две угловые точки в прямоугольник.

box(point '(0,1)', point '(1,0)')(1,1),(0,0)

box ( polygon ) → box

Вычисляет окружающий прямоугольник для многоугольника.

box(polygon '((0,0),(1,1),(2,0))')(2,1),(0,0)

bound_box ( box, box ) → box

Вычисляет окружающий прямоугольник для двух прямоугольников.

bound_box(box '(1,1),(0,0)', box '(4,4),(3,3)')(4,4),(0,0)

circle ( box ) → circle

Вычисляет минимальную окружность, описанную около прямоугольника.

circle(box '(1,1),(0,0)')<(0.5,0.5),0.7071067811865476>

circle ( point, double precision ) → circle

Формирует окружность по точке, задающей центр, и радиусу.

circle(point '(0,0)', 2.0)<(0,0),2>

circle ( polygon ) → circle

Преобразует многоугольник в окружность. Центром окружности будет средняя точка для всех точек многоугольника, а радиусом среднее расстояние от этого центра до точек многоугольника.

circle(polygon '((0,0),(1,3),(2,0))')<(1,1),1.6094757082487299>

line ( point, point ) → line

Преобразует две точки в проходящую через них линию.

line(point '(-1,0)', point '(1,0)'){0,-1,0}

lseg ( box ) → lseg

Вычисляет диагональ прямоугольника в виде отрезка.

lseg(box '(1,0),(-1,0)')[(1,0),(-1,0)]

lseg ( point, point ) → lseg

Формирует отрезок по двум точкам.

lseg(point '(-1,0)', point '(1,0)')[(-1,0),(1,0)]

path ( polygon ) → path

Преобразует многоугольник в замкнутый путь с тем же набором точек.

path(polygon '((0,0),(1,1),(2,0))')((0,0),(1,1),(2,0))

point ( double precision, double precision ) → point

Формирует точку по заданным координатам.

point(23.4, -44.5)(23.4,-44.5)

point ( box ) → point

Вычисляет центр прямоугольника.

point(box '(1,0),(-1,0)')(0,0)

point ( circle ) → point

Вычисляет центр окружности.

point(circle '<(0,0),2>')(0,0)

point ( lseg ) → point

Вычисляет середину отрезка.

point(lseg '[(-1,0),(1,0)]')(0,0)

point ( polygon ) → point

Вычисляет центр многоугольника (среднее арифметическое по координатам его точек).

point(polygon '((0,0),(1,1),(2,0))')(1,0.3333333333333333)

polygon ( box ) → polygon

Преобразует прямоугольник в многоугольник с 4 вершинами.

polygon(box '(1,1),(0,0)')((0,0),(0,1),(1,1),(1,0))

polygon ( circle ) → polygon

Преобразует круг в многоугольник с 12 вершинами.

polygon(circle '<(0,0),2>')((-2,0),​(-1.7320508075688774,0.9999999999999999),​(-1.0000000000000002,1.7320508075688772),​(-1.2246063538223773e-16,2),​(0.9999999999999996,1.7320508075688774),​(1.732050807568877,1.0000000000000007),​(2,2.4492127076447545e-16),​(1.7320508075688776,-0.9999999999999994),​(1.0000000000000009,-1.7320508075688767),​(3.673819061467132e-16,-2),​(-0.9999999999999987,-1.732050807568878),​(-1.7320508075688767,-1.0000000000000009))

polygon ( integer, circle ) → polygon

Преобразует окружность в многоугольник с n вершинами.

polygon(4, circle '<(3,0),1>')((2,0),​(3,1),​(4,1.2246063538223773e-16),​(3,-1))

polygon ( path ) → polygon

Преобразует замкнутый путь в многоугольник с тем же набором точек.

polygon(path '((0,0),(1,1),(2,0))')((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.