Blog Geo.NET Geoprocessamento, SIG e Sensoriamento Remoto

25May/102

Funções PostGIS #3

Boa tarde pessoal!

Vamos falar um pouco hoje das funções de análise espacial e medições. Antes disso, o blog alcançou +50 postagens essa semana. Parabéns para nós!

ST_Area()

Esta função é bastante simples. Ela retorna a área de um polígono ou multipolígono.

-- assinatura
-- SELECT ST_Area(geometria)

SELECT ST_Area(
   ST_GeomFromText(('POLYGON((0 0, 1 0,1 1,0 1,0 0))')))

ST_Perimeter()

Outra função bastante simples, de um único argumento. O argumento deve ser uma geometria do tipo polígono. Se você passar uma LINESTRING, o PostGIS irá retornar 0. Veja ST_Length() para LINESTRINGs.

-- assinatura
-- SELECT ST_Area(geometria)

SELECT ST_Perimeter(
   ST_GeomFromText(('POLYGON((0 0, 1 0,1 1,0 1,0 0))')));

-- só funciona com polígonos. user ST_Length()
SELECT ST_Perimeter(
   ST_GeomFromText('LINESTRING(0 0, 1 0, 2 1, 2 2, 3 2)'));

ST_Perimeter2D()

Calcula o perímetro considerando apenas as coordenadas X e Y de um polígono.

-- assinatura
-- SELECT ST_Perimeter2D(geometria)
-- note que nosso polígono é 3D, possui Z.
SELECT ST_Perimeter2D(
   ST_GeomFromText(('POLYGON((0 0 1, 1 0 1,1 1 2,0 1 3,0 0 1))')));

ST_Perimeter3D()

Calcula o perímetro de um polígono levando em conta as coordenadas Z. Veja que nosso polígono anterior, com a coordenada Z, ST_Perimeter3D() nos dá um retorno diferente.

-- assinatura
-- SELECT ST_Perimeter3D(geometria)
-- note que o polígono é 3D, possui Z.
SELECT ST_Perimeter3d(
   ST_GeomFromText(('POLYGON((0 0 1, 1 0 1,1 1 2,0 1 3,0 0 1))')));

ST_Length()

Calcula o comprimento de uma LINESTRING. Simples e direto :D . Esta função calcula o comprimento de uma linha em duas dimensões.

-- assinatura
-- SELECT ST_Length(geometria)

SELECT ST_Length(
    ST_GeomFromText('LINESTRING(0 0, 1 0, 2 1, 3 3)'));

ST_Length2D()

Exatamente igual à função acima. É apenas um apelido para ST_Length().

ST_Length3D()

Esta função funciona exatamente como ST_Perimeter3D. Mas para LINESTRINGs. Esta função leva em conta as coordenadas no eixo Z de uma geometria.

-- assinatura
-- SELECT ST_Length3D(geometria)

SELECT ST_Length3D(
    ST_GeomFromText('LINESTRING(0 0 1, 0 0 0, 1 0 2, 2 3 1)'));

ST_Centroid()

Esta função calcula o centro de massa de uma geometria. Para pontos é apenas uma média aritmética de seus conjuntos de coordenadas. Para LINESTRINGS, é o resultado de uma média ponderada do comprimento de seus segmentos e para polígonos o centro de massa do mesmo.

É possível aplicar esta função em qualquer tipo de geometria e em coleções genéricas (GEOMETRY_COLLECTIONs - conjuntos de geometrias de diversos tipos), sendo o resultado equivalente ao centróide do conjunto de geometrias de maior dimensionalidade (pontos são 0-dimensionais, linhas unidimensionais, polígonos bidimensionais). Ou seja, se temos um conjunto de pontos, linhas e polígonos, o centróide será igual ao centróide do conjunto de polígonos.

Esta função é importante. Diversas vezes a maneira mais prática e fácil de se transformar dados é através do centróide e preparar dados para estatísticas espaciais.

-- assinatura
-- SELECT ST_Centroid(geometria)

SELECT ST_AsText(
	ST_CENTROID(
	ST_GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')));

SELECT ST_AsText(
	ST_CENTROID(
	ST_GeomFromText('LINESTRING(0 0, 1 0, 1 1)')));

SELECT ST_AsText(
	ST_CENTROID(
	ST_GeomFromText('MULTIPOINT((0 0),(5 8),(10 1))')));

Aqui estão os resultados das chamadas acima.

Resultado da função ST_Centroid utilizando um polígono como argumento

Resultado da função ST_Centroid utilizando um polígono como argumento

Resultado da função ST_Centroid utilizando uma linestring como argumento

Resultado da função ST_Centroid utilizando uma linestring como argumento

Resultado da função ST_Centroid utilizando um multipoint como argumento

Resultado da função ST_Centroid utilizando um multipoint como argumento

ST_Intersects()

Outra função importante. Esta função simplesmente teste se geometria A interseciona geometria B. Esta função não retorna a real interseção das duas partes, mas somente se elas se intersecionam ou não, true ou false. ST_Intersects pode ser utilizado com qualquer par de geometrias.

-- assinatura
-- SELECT ST_Intersercts(geometria_A,geometria_B);

-- retorna true
SELECT ST_Intersects(
	ST_GeomFromText('POLYGON((0 0, 1 1, 1 0, 0 1, 0 0))'),ST_GeomFromText('LINESTRING(0 0, 2 2, 1 1)'));

-- retorna false
SELECT ST_Intersects(
	ST_GeomFromText('POLYGON((0 0, 1 1, 1 0, 0 1, 0 0))'),ST_GeomFromText('LINESTRING(10 10, 20 10)'));

ST_Intersection()

Esta função é parecida com a ST_Intersects, mas esta retorna de fato a interseção entre as duas geometrias. Ambas as funções são computacionalmente intensivas, portanto cuidado ao utilizá-la em um sistema em produção, em views e outras coisas deste tipo. Esta função tem uma particularidade: podemos usar como parametro qualquer tipo de geometria, mas o resultado sempre virá no formato de geometria com menor dimensionalidade.

Exemplo: se computarmos a interseção entre dois polígonos, teremos como resultado um polígono (ou nulo). Se computarmos a interseção entre um polígono e diversas linhas, o resultado será uma LINESTRING obrigatoriamente. Porque? É matemático, a interseção de um polígono com um ponto sempre terá como resultado um ponto. Os resultados estão em verde.

Veja:

Resultado gráfico da interseção de duas LINESTRINGs

Resultado gráfico da interseção de duas LINESTRINGs

Podemos ter como resultado da interseção entre duas LINESTRINGs um conjunto de pontos ou uma LINESTRING (quando dois segmentos são coincidentes).

Resultado gráfico da interseção de um conjunto de pontos e um polígono

Resultado gráfico da interseção de um conjunto de pontos e um polígono

Resultado gráfico de ST_Intersection entre um conjunto de LINESTRINGs e um polígono

Resultado gráfico de ST_Intersection entre um conjunto de LINESTRINGs e um polígono

Resultado gráfico de ST_Intersection entre dois polígonos

Resultado gráfico de ST_Intersection entre dois polígonos

Vamos à assinatura da função:

-- assinatura
-- SELECT ST_Intersection(geometria_A,geometria_B);

-- POLYGON e LINESTRING
SELECT ST_AsText(ST_Intersection(
	ST_GeomFromText('POLYGON((0 0,1 0, 1 1,0 1,0 0))'),
        ST_GeomFromText('LINESTRING(0 0,.5 .5,2 2,3 3)')));

-- POLYGON E PONTO
SELECT ST_AsText(ST_Intersection(
	ST_GeomFromText('POLYGON((0 0,1 0, 1 1,0 1,0 0))'),
        ST_GeomFromText('POINT(.2 .2)')))

-- POLYGON e POLYGON
SELECT ST_AsText(ST_Intersection(
	ST_GeomFromText('POLYGON((0 0,1 0, 1 1,0 1,0 0))'),
	ST_GeomFromText('POLYGON((.5 .5,1.5 .5,1.5 1.5,.5 1.5,.5 .5))')))

-- LINESTRING e LINESTRING
SELECT ST_AsText(ST_Intersection(
	ST_GeomFromText('LINESTRING(0 0,1 1,3 2,6 6)'),
	ST_GeomFromText('LINESTRING(-1 -1,.5 .5,3 4,5 6)')))

Os resultados em formato texto são os seguintes:

Resultado textual de ST_Intersection entre um polígono e uma linestring

Resultado textual de ST_Intersection entre um polígono e uma linestring

Resultado textual de ST_Intersection entre um polígono e um ponto

Resultado textual de ST_Intersection entre um polígono e um ponto

Resultado textual de ST_Intersection entre dois polígonos

Resultado textual de ST_Intersection entre dois polígonos

Resultado textual de ST_Intersection entre duas LINESTRINGs

Resultado textual de ST_Intersection entre duas LINESTRINGs

Uma nota importante: pontos não se intersecionam. Ou eles são coincidentes ou não.

ST_Overlaps

Esta função é parecida em funcionamento com a ST_Intersects. Na verdade ela realiza a mesma operação que ST_Intersects, mas leva em consideração se um objeto não está contido plenamente dentro do outro. Esta função opera com qualquer tipo de geometria, mas presta atenção na dimensionalidade de cada uma: uma geometria de menor dimensionalidade está sempre contida na geometria de maior dimensionalidade, portanto, não sobrepõe a de maior dimensionalidade.

Exemplo: geometria_a é um ponto e geometria_b é um polígono. Se perguntado se ST_Overlaps(geometria_a,geometria_b), o PostGIS vai retornar falso, pois não são da mesma dimensionalidade. Se geometria_a é um polígono e geometria_b também, a operação pode retornar verdadeiro, caso a sobreposição ocorra.

-- assinatura
-- SELECT ST_Overlaps(geometria_a,geometria_b)

-- [1]
-- mesma dimensionalidade: estas geometrias podem se sobrepor.
SELECT ST_Overlaps(
	ST_GeomFromText('LINESTRING(0 0,1 1,3 2,6 6)'),
	ST_GeomFromText('LINESTRING(-1 -1,.5 .5,3 4,5 6)'))

-- [2]
-- mesma dimensionalidade: estas geometrias podem se sobrepor.
SELECT ST_Overlaps(
	ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))'),
	ST_GeomFromText('POLYGON((.5 .5,1.5 .5,1.5 1.5,.5 1.5,.5 .5))'))

-- [3]
-- dimensionalidade diferente: estas geometrias não podem se sobrepor (mesmo que se intersecionem)
SELECT ST_Overlaps(
	ST_GeomFromText('LINESTRING(0 0,1 1,3 2,6 6)'),
	ST_GeomFromText('POINT(0 0)'));

-- [4]
-- dimensionalidade diferente: estas geometrias não podem se sobrepor (mesmo que se intersecionem)
SELECT ST_Overlaps(
	ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))'),
	ST_GeomFromText('POINT(0 0)'));
Resultado da função ST_Overlaps nos exemplos 1 e 2 de ST_Overlaps

Resultado da função ST_Overlaps nos exemplos 1 e 2 de ST_Overlaps

Resultado da função ST_Overlaps nos exemplos 3 e 4 de ST_Overlaps

Resultado da função ST_Overlaps nos exemplos 3 e 4 de ST_Overlaps

ST_Covers()

Esta função retorna verdadeiro caso nenhum ponto da geometria_b se encontre fora da geometria_a.

-- assinatura
-- SELECT ST_Covers(geometria_a,geomtria_b);

-- geometria_a cobre geometria_b? verdadeiro
SELECT ST_Covers(
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'),
	ST_GeomFromText('POLYGON((.5 .5,1.5 .5,1.5 1.5,.5 1.5,.5 .5))'));

-- geometria_a cobre geometria_b? verdadeiro, todos os pontos de geometria_b estão contidos em a
SELECT ST_Covers(
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'),
	ST_GeomFromText('POINT(1 1)'));

-- geometria_a cobre geometria_b? falso. geometria_a é menor que geometria_a.
SELECT ST_Covers(
	ST_GeomFromText('POLYGON((.5 .5,1.5 .5,1.5 1.5,.5 1.5,.5 .5))'),
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'));

-- geometria_a cobre geometria_b? falso. geometria_a cobre geometria_b parcialmente (note o segundo ponto, em 100 100)
SELECT ST_Covers(
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'),
	ST_GeomFromText('MULTIPOINT((1 1),(100 100))'));
Resultado da função ST_Covers utilizando com dois polígonos

Resultado da função ST_Covers utilizando com dois polígonos

Resultado da função ST_Covers entre um polígono e multipontos

Resultado da função ST_Covers entre um polígono e multipontos

ST_Within()

Esta função é similar em funcionamento à ST_Covers(). A diferença aqui é que esta retorna positivo se estiver completamente dentro de B.

-- assinatura
-- SELECT ST_Within(geometria_a,geometria_b)

-- [1]
-- geometria_a está completamente dentro de geometria_b? verdadeiro
SELECT ST_Within(
	ST_GeomFromText('POINT(5 5)'),
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'));

-- [2]
-- geometria_a está completamente dentro de geometria_b? verdadeiro
SELECT ST_Within(
	ST_GeomFromText('LINESTRING(5 5, 2 3, 1 0)'),
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'));

-- [3]
-- geometria_a está completamente dentro de geometria_b? verdadeiro
SELECT ST_Within(
	ST_GeomFromText('POLYGON((1 1,2 1,2 2,1 2,1 1))'),
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'));

-- [4]
-- geometria_a está completamente dentro de geometria_b? falso. geometrias de dimensionalidade menor não contém geometrias de maior
-- dimensionalidade
SELECT ST_Within(
	ST_GeomFromText('POLYGON((1 1,2 1,2 2,1 2,1 1))'),
	ST_GeomFromText('MULTIPOINT((0 0),(10 0),(10 10),(0 10),(0 0))'));

-- [5]
-- geometria_a está completamente dentro de geometria_b? falso. A não está inteiramente dentro de B
SELECT ST_Within(
	ST_GeomFromText('MULTIPOINT((5 5),(100 100))'),
	ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0))'));
Resultado da função ST_Within(), exemplos de 1 à 3

Resultado da função ST_Within(), exemplos de 1 à 3

Resultado da função ST_Within, exemplos 4 e 5

Resultado da função ST_Within, exemplos 4 e 5

Por agora é só pessoal. No próximo post vou tentar explicar melhor sobre a dimensionalidade de cada tipo de geometria e os porquês estas funções se comportam desta maneira.

Espero que tenham gostado.

Abraços

George R. C. Silva

Related posts:

  1. Funções PostGIS #2
  2. Funções PostGIS #1
  3. Brincando com ArcObjects #2
  4. Construindo funcionalidades para o WKT Raster
  5. Brincando com ArcObjects
Comments (2) Trackbacks (0)
  1. Muito bom George, como sempre. Algumas dessas funções eu nem lembrava que existia :D
    Abraço e parabéns.

  2. Obrigado Anderson,

    Como sempre tentamos o melhor.

    Obrigado pela visita e comentário.


Leave a comment


No trackbacks yet.

Get Adobe Flash playerPlugin by wpburn.com wordpress themes