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

Для геометрических типов point (точка), box (прямоугольник), lseg (отрезок), line (прямая), path (путь), polygon (многоугольник) и circle (окружность) существует большой набор встроенных вспомогательных функций и операторов, приведенных в подразделах Геометрические операторы, Геометрические функции и Функции преобразования геометрических типов.



Геометрические операторы

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

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

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

path + path → path

Конкатенирует два открытых пути (возвращает 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 (воспринимая точки как комплексные числа, представленные действительной и мнимой частями, и проводя стандартное комплексное умножение). Если интерпретировать второй аргумент типа point как вектор, это равнозначно увеличению размера объекта и расстояния от начала координат при помощи длины этого вектора с поворотом объекта против часовой стрелки относительно начала координат на угол, равный углу между вектором и осью x. Имеется для типов point, box1, 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 (воспринимая точки как комплексные числа, представленные действительной и мнимой частями, и проводя стандартное комплексное деление). Если интерпретировать второй аргумент типа point как вектор, это равнозначно уменьшению размера объекта и расстояния от начала координат при помощи длины этого вектора с поворотом объекта по часовой стрелки относительно начала координат на угол, равный углу между вектором и осью x. Имеется для типов point, box1, 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))
1

При «повороте» прямоугольника с помощью этих операторов перемещаются только его угловые точки: стороны этого прямоугольника по-прежнему считаются параллельными осям. Как следствие, в отличие от истинного поворота, при этой операции размер прямоугольника меняется.

@-@ геометрический_тип → 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.

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

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

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

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

box # box → box

Вычисляет пересечение двух прямоугольников или возвращает 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

Пересекаются ли эти объекты? (Для результата true достаточно одной общей точки.) Имеется для типов 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 <^ box → boolean

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

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

box >^ box → boolean

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

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

?- line → boolean

?- lseg → boolean

Горизонтальна ли эта линия?

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

point ?- point → boolean

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

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

?| line → boolean

?| lseg → boolean

Вертикальна ли эта линия?

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

point ?| point → boolean

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

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

line ?-| line → boolean

lseg ?-| lseg → boolean

Перпендикулярны ли эти линии?

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

line ?|| line → boolean

lseg ?|| lseg → boolean

Параллельны ли эти линии?

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

ВНИМАНИЕ!
Обратите внимание, что оператор «тождественности», ~=, представляет собой обычную проверку равенства для типов point, box, polygon и circle. Для некоторых геометрических типов также имеется оператор =, но = проверяет только равенство площадей. Другие скалярные операторы сравнения (<= и т. п.) для тех типов, для которых они имеются, также сравнивают площади.

Примечание
До QHB 1.5.2 операторы сравнения point <<| point (строго ниже) и point |>> point (строго выше) назывались <^ и >^ соответственно. Эти имена все еще доступны, но являются устаревшими и в итоге будут удалены.



Геометрические функции

area

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

Вычисляет площадь. Имеется для типов box, path, circle. Входное значение типа path (путь) должно быть закрытым, иначе возвращается NULL. Кроме того, если этот путь является самопересекающимся, результат может не иметь смысла.

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

center

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

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

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

diagonal

diagonal ( box ) → lseg

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

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

diameter

diameter ( circle ) → double precision

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

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

height

height ( box ) → double precision

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

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

isclosed

isclosed ( path ) → boolean

Это закрытый путь?

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

isopen

isopen ( path ) → boolean

Это открытый путь?

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

length

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

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

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

npoints

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

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

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

pclose

pclose ( path ) → path

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

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

popen

popen ( path ) → path

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

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

radius

radius ( circle ) → double precision

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

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

slope

slope ( point, point ) → double precision

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

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

width

width ( box ) → double precision

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

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


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

box

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

bound_box ( box, box ) → box

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

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

circle

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

line ( point, point ) → line

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

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

lseg

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

path ( polygon ) → path

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

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

point

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

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.