9.11. Funções e operadores geométricos #

Os tipos de dados geométricos point, box, lseg, line, path, polygon e circle possuem um grande conjunto de funções e operadores de suporte nativos, descritos na Tabela 9.36, na Tabela 9.37 e na Tabela 9.38.

Tabela 9.36. Operadores geométricos

Operador

Descrição

Exemplo(s)

tipo_geométrico + pointtipo_geométrico

Adiciona as coordenadas do segundo argumento (do tipo de dados point) às de cada ponto do primeiro argumento, realizando assim a translação. Disponível para os tipos de dados point, box, path e circle.

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

path + pathpath

Concatena dois caminhos abertos (retorna nulo se um dos caminhos for fechado).

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

tipo_geométrico - pointtipo_geométrico

Subtrai as coordenadas do segundo argumento (do tipo de dados point) às de cada ponto do primeiro argumento, realizando assim a translação. Disponível para os tipos de dados point, box, path e circle.

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

tipo_geométrico * pointtipo_geométrico

Multiplica cada ponto do primeiro argumento pelo segundo argumento (do tipo de dados point) (tratando o ponto como número complexo, representado pelas partes real e imaginária, e realizando a multiplicação complexa padrão — (a, b) . (c, d) = (ac - bd, ad + bc)). Se o segundo argumento (do tipo de dados point) for interpretado como um vetor, isto equivale a mudar o tamanho e distância do objeto da origem baseado no comprimento do vetor, e girá-lo no sentido anti-horário em torno da origem pelo ângulo do vetor a partir do eixo x. Disponível para os tipos de dados point, box[a], path e 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))

tipo_geométrico / pointtipo_geométrico

Divide cada ponto do primeiro argumento pelo segundo argumento (do tipo de dados point) (tratando o ponto como número complexo, representado pelas partes real e imaginária, e realizando a divisão complexa padrão). Se o segundo argumento (do tipo de dados point) for interpretado como um vetor, isto equivale a mudar o tamanho e distância do objeto da origem baseado no comprimento do vetor, e girá-lo no sentido horário em torno da origem pelo ângulo do vetor a partir do eixo x. Disponível para os tipos de dados point, box[a], path e 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))

@-@ tipo_geométricodouble precision

Calcula o comprimento total. Disponível para os tipos de dados lseg e path.

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

@@ tipo_geométricopoint

Calcula o ponto central. Disponível para os tipos de dados box, lseg, polygon e circle.

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

# tipo_geométricointeger

Retorna o número de pontos. Disponível para os tipos de dados path e polygon.

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

tipo_geométrico # tipo_geométricopoint

Calcula o ponto de interseção, ou nulo, caso não haja nenhum. Disponível para os tipos de dados lseg e line.

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

box # boxbox

Calcula a interseção de duas caixas, ou nulo, caso não haja nenhuma.

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

tipo_geométrico ## tipo_geométricopoint

Calcula o ponto mais próximo do primeiro objeto no segundo objeto. Disponível para estes pares de tipos de dados: (point, box), (point, lseg), (point, line), (lseg, box), (lseg, lseg), (line, lseg).

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

tipo_geométrico <-> tipo_geométricodouble precision

Calcula a distância entre dois objetos. Disponível para todos os tipos de dados geométricos, para todas as combinações do tipo de dados point com outro tipo de dados geométrico, e para estes pares adicionais de tipos de dados: (box, lseg), (lseg, line), (polygon, circle) (e os casos de comutação).

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

tipo_geométrico @> tipo_geométricoboolean

O primeiro objeto contém o segundo objeto? Disponível para estes pares de tipos de dados: (box, point), (box, box), (path, point), (polygon, point), (polygon, polygon), (circle, point), (circle, circle).

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

tipo_geométrico <@ tipo_geométricoboolean

O primeiro objeto está contido no segundo objeto? Disponível para estes pares de tipos de dados: (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

tipo_geométrico && tipo_geométricoboolean

Esses objetos se sobrepõem? (Um ponto em comum faz com que seja verdade.) Disponível para os tipos de dados box, polygon e circle.

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

tipo_geométrico << tipo_geométricoboolean

O primeiro objeto está inteiramente à esquerda do segundo objeto? Disponível para os tipos de dados point, box, polygon e circle.

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

tipo_geométrico >> tipo_geométricoboolean

O primeiro objeto está inteiramente à direita do segundo objeto? Disponível para os tipos de dados point, box, polygon e circle.

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

tipo_geométrico &< tipo_geométricoboolean

O primeiro objeto não se estende à direita do segundo objeto? Disponível para os tipos de dados box, polygon e circle.

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

tipo_geométrico &> tipo_geométricoboolean

O primeiro objeto não se estende à esquerda do segundo objeto? Disponível para os tipos de dados box, polygon e circle.

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

tipo_geométrico <<| tipo_geométricoboolean

O primeiro objeto está inteiramente abaixo do segundo objeto? Disponível para os tipos de dados point, box, polygon e circle.

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

tipo_geométrico |>> tipo_geométricoboolean

O primeiro objeto está inteiramente acima do segundo objeto? Disponível para os tipos de dados point, box, polygon e circle.

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

tipo_geométrico &<| tipo_geométricoboolean

O primeiro objeto não se estende acima do segundo objeto? Disponível para os tipos de dados box, polygon e circle.

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

tipo_geométrico |&> tipo_geométricoboolean

O primeiro objeto não se estende abaixo do segundo objeto? Disponível para os tipos de dados box, polygon e circle.

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

box <^ boxboolean

O primeiro objeto está abaixo do segundo objeto (permite que os lados se toquem)?

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

box >^ boxboolean

O primeiro objeto está acima do segundo objeto (permite que os lados se toquem)?

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

tipo_geométrico ?# tipo_geométricoboolean

Esses objetos se intersectam? Disponível para estes pares de tipos de dados: (box, box), (lseg, box), (lseg, lseg), (lseg, line), (line, box), (line, line), (path e path).

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

?- lineboolean

?- lsegboolean

A linha é horizontal?

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

point ?- pointboolean

Os pontos estão alinhados horizontalmente (ou seja, todos têm a mesma coordenada y)?

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

?| lineboolean

?| lsegboolean

A linha é vertical?

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

point ?| pointboolean

Os pontos estão alinhados verticalmente (ou seja, todos têm a mesma coordenada x)?

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

line ?-| lineboolean

lseg ?-| lsegboolean

As linhas são perpendiculares?

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

line ?|| lineboolean

lseg ?|| lsegboolean

As linhas são paralelas?

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

tipo_geométrico ~= tipo_geométricoboolean

Esses objetos são o mesmo? Disponível para os tipos de dados point, box, polygon e circle.

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

[a] Rotacionar uma caixa com estes operadores só move seus pontos do canto: a caixa ainda é considerada tendo os lados paralelos aos eixos. Portanto, o tamanho da caixa não é preservado, como aconteceria numa rotação de verdade.


Cuidado

Note que o operador o mesmo que, ~=, representa a noção usual de igualdade para os tipos de dados point, box, polygon e circle. Alguns tipos de dados geométricos também possuem o operador =, mas = compara áreas iguais apenas. Os outros operadores escalares de comparação (<= e assim por diante), quando estão disponíveis para estes tipos de dados, da mesma forma comparam áreas.

Nota

Antes do PostgreSQL 14, os operadores de comparação de ponto acima/abaixo de outro ponto (point <<| point) e (point |>> point) eram chamados, respectivamente, de <^ e >^. Esses nomes ainda estão disponíveis, mas estão em obsolescência e deverão ser removidos.

Tabela 9.37. Funções geométricas

Função

Descrição

Exemplo(s)

area ( tipo_geométrico ) → double precision

Calcula a área. Disponível para os tipos de dados box, path e circle. O tipo de dados path da entrada deve ser fechado, senão é retornado o valor nulo. Também, se o tipo de dados path for auto-interseccionado, o resultado poderá não fazer sentido.

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

center ( tipo_geométrico ) → point

Calcula o ponto central. Disponível para os tipos de dados box e circle.

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

diagonal ( box ) → lseg

Extrai a diagonal da caixa como um segmento de linha (idêntica à função lseg(box)).

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

diameter ( circle ) → double precision

Calcula o diâmetro do círculo.

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

height ( box ) → double precision

Calcula o tamanho vertical da caixa.

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

isclosed ( path ) → boolean

O caminho é fechado?

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

isopen ( path ) → boolean

O caminho é aberto?

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

length ( tipo_geométrico ) → double precision

Calcula o comprimento total. Disponível para os tipos de dados lseg, path.

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

npoints ( tipo_geométrico ) → integer

Retorna o número de pontos. Disponível para os tipos de dados path, polygon.

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

pclose ( path ) → path

Converte o caminho em uma forma fechada.

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

popen ( path ) → path

Converte o caminho em uma forma aberta.

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

radius ( circle ) → double precision

Calcula o raio do círculo.

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

slope ( point, point ) → double precision

Calcula a inclinação de uma linha traçada através dos dois pontos.

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

width ( box ) → double precision

Calcula o tamanho horizontal da caixa.

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


Tabela 9.38. Funções de conversão de tipo de dados geométrico

Função

Descrição

Exemplo(s)

box ( circle ) → box

Calcula a caixa inscrita dentro do círculo.

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

box ( point ) → box

Converte ponto em caixa vazia.

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

box ( point, point ) → box

Converte quaisquer dois pontos de canto em caixa.

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

box ( polygon ) → box

Calcula a caixa delimitadora do polígono.

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

bound_box ( box, box ) → box

Calcula a caixa delimitadora de duas caixas.

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

circle ( box ) → circle

Calcula o menor círculo que envolve uma caixa.

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

circle ( point, double precision ) → circle

Constrói o círculo a partir do centro e do raio.

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

circle ( polygon ) → circle

Converte polígono em círculo. O centro do círculo é a média das posições dos pontos do polígono, e o raio é a distância média dos pontos do polígono a partir desse centro.

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

line ( point, point ) → line

Converte dois pontos na linha que passa por eles.

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

lseg ( box ) → lseg

Extrai a diagonal da caixa como um segmento de linha.

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

lseg ( point, point ) → lseg

Constrói segmento de linha a partir de dois pontos finais.

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

path ( polygon ) → path

Converte o polígono em um caminho fechado com a mesma lista de pontos.

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

point ( double precision, double precision ) → point

Constrói um ponto a partir de suas coordenadas.

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

point ( box ) → point

Calcula o centro da caixa.

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

point ( circle ) → point

Calcula o centro do círculo.

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

point ( lseg ) → point

Calcula o centro do segmento de linha.

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

point ( polygon ) → point

Calcula o centro do polígono (a média das posições dos pontos do polígono).

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

polygon ( box ) → polygon

Converte a caixa em um polígono de 4 pontos.

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

polygon ( circle ) → polygon

Converte o círculo em um polígono de 12 pontos.

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

Converte o círculo em um polígono de n pontos.

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

polygon ( path ) → polygon

Converte o caminho fechado em um polígono com a mesma lista de pontos.

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


É possível acessar os dois números componentes de um tipo de dados point como se o ponto fosse uma matriz com índices 0 e 1. Por exemplo, se t.p for uma coluna do tipo de dados point, então SELECT p[0] FROM t irá recuperar a coordenada X, e UPDATE t SET p[1] = ... irá atualizar a coordenada Y. Da mesma forma, um valor do tipo de dados box ou lseg pode ser tratado como uma matriz de dois valores do tipo de dados point.