terça-feira, dezembro 03, 2013

Caracterização Morfométrica de Bacias Hidrográficas utilizando o GRASS

A caracterização morfométrica tem como objetivo esclarecer várias questões associadas ao relevo e a dinâmica do escoamento superficial de uma bacia hidrográfica. Tal caracterização é feita com base nas principais medidas físicas e serve de instrumento para diversas aplicações relacionadas aos recursos hídricos.

Utilizando a extensão r.basin do GRASS, é possível extrair os atributos hidrológicos que compõem a caracterização morfométrica, para tanto, é necessário que o usuário informe a coordenada do exutório da bacia hidrográfica. Neste exemplo irei utilizar a imagem SRTM SB-24-Z-C como área de estudo.

1 - Convertendo o sistema de projeção da imagem SRTM para UTM


Utilizando o terminal, entre na pasta que contém a imagem e digite o seguinte comando:
$ gdalwarp -s_srs "EPSG:4326" -t_srs "EPSG:31984" SB-24-Z-C.tif dem.tif

Desta forma o raster será reprojetado para a projeção UTM Fuso 24 Sul (Datum SIRGAS 2000).

2 - Configurando a Location e o Mapset do GRASS


Abra o GRASS na janela do terminal (digitando "grass") e siga os próximos passos:

  • Escolha Location Wizard:

  • Defina o nome da Location e clique em next:

  • Na próxima tela, escolha a opção indicada abaixo:

  • Clique em "Browse" e procure o raster dem.tif:

  • Será exibida a tela de sumário, clique em "Finish"

  • No próximo passo, clique em "Yes":

  • Defina o nome do mapset e clique em "Start GRASS":



3 - Modificando as cores do Raster:


No terminal onde a sessão do GRASS está aberto, digite:
$ r.colors map=dem color=elevation

Para visualizar o resultado no  "Map Display", adicione esta camada através da opção "Add rast map layer" (Control + Shift + r):


4 - Preparando o MDE para a análise morfométrica:


Com o comando r.fill.dir são removidos os "sinks" (células cercadas por outras com maiores elevações), que produzem a descontinuidade do escoamento superficial descendente para uma célula vizinha.
$ r.fill.dir input=dem elevation=dem.filled direction=filled.dir


O próximo passo consiste em criar duas superfícies para análises hidrológicas através do comando r.watershed, são elas: a superfície de fluxo acumulado (accumulation) e a rede de drenagem matricial (streams).
$ r.watershed -fa elevation=dem.filled accumulation=accumulation \
stream=streams convergence=5 threshold=62

OBS: O threshold define o tamanho mínimo a ser considerado como uma área de contribuição para a bacia hidrográfica.
Para áreas de 0,5 km2 (500.000 m2) foi utilizado um valor igual a 62  (500.000 / 90x90), onde 90x90 é a resolução espacial de uma imagem SRTM).

5 - Instalando as extensões necessárias:


Instale uma a uma, as extensões a seguir:
$ g.extension extension=r.stream.angle
$ g.extension extension=r.stream.basins
$ g.extension extension=r.stream.del
$ g.extension extension=r.stream.distance
$ g.extension extension=r.stream.extract
$ g.extension extension=r.stream.order
$ g.extension extension=r.stream.pos
$ g.extension extension=r.stream.preview
$ g.extension extension=r.stream.stats
$ g.extension extension=r.ipso
$ g.extension extension=r.wf

E por último, a extensão r.basin:
$ g.extension extension=r.basin


6 - Realizando a caracterização morfométrica:


Deve-se escolher como coordenada do exutório um ponto que toque a rede de drenagem matricial, neste caso a coordenada escolhida foi a seguinte: (619.241,988946 E || 9.207.668,119428 N)
$ r.basin map=dem.filled prefix=out \ 
easting=619241.988946 northing=9207668.119428 threshold=62

7- Resultados:


O comando r.basin gera os seguintes resultados:

  • Layers: limite da bacia hidrográfica, rio principal, exutório e rede de drenagem da bacia:
  • Gráfico: Curva hipsométrica:

  • Planilha: é gerado um arquivo csv contendo o resultado da análise:


  • Saída no terminal:


quarta-feira, outubro 16, 2013

Instalação do PostGIS 2.0 no Ubuntu via Terminal

Este tutorial é uma atualização da postagem:

 

1 - Atualizando a Distribuição:

 

Antes de começar a instalação do PostGIS 2.0, é importante atualizar a lista de pacotes e realizar a atualização do sistema. Também é necessário adicionar os repositórios indicados pelo Wiki do PostGIS:
$ sudo apt-get install python-software-properties
$ sudo apt-add-repository ppa:sharpie/for-science
$ sudo apt-add-repository ppa:sharpie/postgis-stable
$ sudo apt-add-repository ppa:ubuntugis/ubuntugis-unstable
$ sudo apt-get update && sudo apt-get upgrade -y

 

2 - Instalando o PostgreSQL, PostGIS e o PgAdmin:

 

$ sudo apt-get install postgresql-9.1 postgresql-9.1-postgis-2.0 pgadmin3

 

3 - Criando o banco de dados postgis:

 

Troque o seu usuário para o usuário postgres com os comandos:
$ sudo su
$ su postgres
E crie o banco de dados postgis:
$ createdb postgis
Em seguida, crie um usuário para acessar o SGBD com o comando createuser nome_do_usuario, onde nome_do_usuario pode ser o seu usuário Ubuntu, no meu caso o comando ficou assim:
$ postgres@ubuntu:/home/marcello$ createuser marcello -P
Enter password for new role: 
Enter it again: 
Shall the new role be a superuser? (y/n) y
No ambiente de desenvolvimento é mais prático que esta senha seja a mesma do seu usuário, porém isso é opcional. Agora troque o usuário postgres para o seu usuário, no meu caso:
$ su marcello

 

4 - Carregando as funções espaciais no banco postgis:


Acesse o banco e digite a instrução CREATE EXTENSION postgis;
$ psql postgis
psql (9.1.10)
Type "help" for help.

postgis=# CREATE EXTENSION postgis;

Ou se preferir, carregue individualmente os módulos da extensão, da seguinte forma:


Navegue até a pasta /usr/share/postgresql/9.1/contrib/postgis-2.0/:
$ cd /usr/share/postgresql/9.1/contrib/postgis-2.0/
E carregue os arquivos SQL a seguir:
$ psql -f postgis.sql -d postgis
$ psql -f spatial_ref_sys.sql -d postgis
$ psql -f legacy.sql -d postgis
$ psql -f rtpostgis.sql -d postgis
$ psql -f topology.sql -d postgis

5 - Criando um banco de dados espacial a partir do banco postgis:

 

Para criar novos bancos de dados espaciais a partir do banco postgis criado anteriormente, utilize o comando createdb com a flag -T (template), exemplo:
$ createdb bd_espacial -T postgis

 

6 - Acessando o banco criado com o PgAdmin:

 

Abra o PgAmin e acesse o menu "file > Add Server...", configure-o como mostra a figura abaixo, lembrando de adicionar o seu usuário:


A instalação foi concluída, é possível ver a versão do PostGIS no banco "bd_espacial" utilizando: SELECT postgis_version(); , como mostra a figura abaixo:


sexta-feira, setembro 27, 2013

Krigagem Ordinária no R

O código abaixo exemplifica a utilização da Krigagem Ordinária utilizando o R dentro de uma sessão do GRASS. O intuito desta postagem é mostrar a codificação básica necessária para se chegar a um primeiro resultado e não será abordado aqui como realizar o ajuste do variograma.



Foram utilizados 300 pontos cotados para gerar a superfície mostrada na Figura 1.

Figura 1 - Resultado da Krigagem

sexta-feira, agosto 09, 2013

PostGIS: Snapping points to lines

Esta é uma releitura da postagem GRASS: Snapping points to lines utilizando a extensão PostGIS, desta forma ficou bem mais simples e rápida a solução, confira:


Consulta no plugin Rt SQL Layer (QGIS)

Resultado no QGIS (Layer nearpoints)

domingo, agosto 04, 2013

Renomeando e Ordenando Campos de um Shapefile via Terminal

Quando trabalhamos com dados vetoriais, frequentemente temos que renomear e ordenar os campos que compõem um arquivo .dbf de um shapefile. O que muita gente não sabe é que isso pode ser feito sem a necessidade de abrir um software de SIG, utilizando a biblioteca OGR através do seguinte comando:
ogr2ogr -a_srs <EPSG:num> <novo_shapefile> <shapefile> -sql "SELECT campo1 AS novo_campo1, campo_2 AS novo_campo2, ..., campoN AS novo_campoN FROM shapefile"
Isto pode ser útil principalmente se o arquivo tiver muitos megabytes (MB), pois este processo pode ser bem demorado, independente do software que você esteja utilizando. Vejamos o exemplo a seguir:

Primeiro utilizando o comando ogrinfo, para obter as informações necessárias sobre o shapefile munipb.shp:
ogrinfo -summary munipb.shp munipb
INFO: Open of `munipb.shp'
      using driver `ESRI Shapefile' successful.

Layer name: munipb
Geometry: Polygon
Feature Count: 224
Extent: (-38.764870, -8.302541) - (-34.793335, -6.026173)
Layer SRS WKT:
GEOGCS["GCS_South_American_1969",
    DATUM["South_American_Datum_1969",
        SPHEROID["GRS_1967_Modified",6378160.0,298.25]],
    PRIMEM["Greenwich",0.0],
    UNIT["Degree",0.0174532925199433]]
NOMEMUNIC: String (50.0)
ARp: Integer (10.0)
UF: String (2.0)
ID_UF: Real (11.0)
REGIAO: String (20.0)
MESOREGIAO: String (50.0)
MICROREGIA: String (50.0)
geocode: String (12.0)
Area_km2: Real (6.2)
per_km: Real (6.2)
id_: Integer (10.0)
O novo shapefile (municipios.shp) será reestruturado com os seguintes campos fid (campo do tipo autoincremento criado automaticamente), geocodigo (geocode), nome (NOMEMUNIC),  micro (MICROREGIA), meso (MESOREGIAO), e area_km2 (Area_km2):
ogr2ogr -a_srs EPSG:4291 municipios.shp munipb.shp -sql "SELECT fid, geocode AS geocodigo, nomemunic AS nome, microregia AS micro, mesoregiao AS meso, area_km2 AS area_km2 FROM munipb"
O resultado pode ser visto com o comando ogrinfo ou em qualquer software de SIG (Figura 1):
ogrinfo -summary municipios.shp municipios
INFO: Open of `municipios.shp'
      using driver `ESRI Shapefile' successful.

Layer name: municipios
Geometry: Polygon
Feature Count: 224
Extent: (-38.764870, -8.302541) - (-34.793335, -6.026173)
Layer SRS WKT:
GEOGCS["SAD69",
    DATUM["South_American_Datum_1969",
        SPHEROID["GRS_1967",6378160,298.247167427]],
    PRIMEM["Greenwich",0],
    UNIT["Degree",0.017453292519943295]]
fid: Integer (10.0)
geocodigo: String (12.0)
nome: String (50.0)
micro: String (50.0)
meso: String (50.0)
area_km2: Real (6.2)
Figura 1 - Tabela reestruturada aberta no QGIS

sábado, julho 20, 2013

QGIS: cáculo da precipitação média pelo método de Thiessen

O cálculo da precipitação média em uma bacia hidrográfica é realizado através de dados coletados por pluviômetros que estão em áreas próximas e/ou dentro da mesma. Por definição a precipitação média é a lâmina d'água de altura uniforme sobre toda a área considerada, associada a um período de tempo.

O método de Thiessen é um dos mais usuais para a determinação da precipitação média, consiste em atribuir um fator de peso aos totais precipitados em cada pluviômetro, proporcionais a área de influência de cada um (VILLELA, 1975). Este método será demonstrado a seguir no Software Quantum GIS.

Na figura abaixo temos três layers abertos no QGIS, rainfall_gauges (estações pluviométricas com dados totais mensais de precipitação), streams (rede de drenagem) e basin (bacia hidrográfica em estudo).



Para criar os polígonos de Thiessen, acesse o menu Vector > Geometry Tools > Voronoi Polygons:



Escolha a camada dos postos pluviométricos, se necessário aplique um buffer para que o layer gerado cubra toda a bacia:



Em seguida corte o layer criado em função do limite da bacia. Vá em Vector > Geoprocessing Tools > Clip:



Em Input vector layer escolha o layer dos polígonos de Thiessen e em Clip layer escolha a bacia hidrográfica:


Com as áreas de influência dos postos pluviométricos definidas (figura abaixo), serão criados alguns campos na tabela de atributos.



Habilite o modo de edição e clique em Open field calculator:


Crie o campo area_km2, neste caso os dados estão em UTM e para obter os resultados em km2 deve-se dividir por 1.000.000. Salve o resultado e saia do modo de edição.


Em seguida, vá em Vector > Analysis Tools > Basic statistics:



Obtenha as estatísticas do Layer basin_thiessen, deve ser anotado o valor da soma das áreas (Sum = 3179.0643), que corresponde a área total da bacia.


Habilite o modo de edição mais uma vez para o layer thiessen_basin e crie mais um campo (area_per) contendo o valor da área de cada polígono dividida pela área total da bacia, em seguida salve a edição:


O último campo a ser criado armazenará o valor da precipitação ponderada (rainfall_p), obtido a partir da multiplicação dos valores dos campos rainfall_m e area_per, em seguida salve as alterações e saia do modo de edição:



Para obter o valor da precipitação média, acesse o menu Vector > Analysis Tools > Basic statistics e escolha o campo rainfall_p:


Em Sum temos o resultado para a precipitação média mensal, que é de 24,72 mm.

O mesmo procedimento pode ser realizado no GRASS através dos comandos abaixo:

Referências:

VILLELA, sm; MATOS, A. Hidrologia aplicada. 1975.

domingo, julho 14, 2013

Pivot Table no PostgreSQL

Pivot Table (ou Crosstab) é uma análise que resulta na inversão de linhas por colunas em uma consulta SQL. Funciona de forma semelhante a uma matriz inversa e seu uso resume uma série de registos em uma tabela mais fácil de ser interpretada, por exemplo:

Figura 1 - Conjunto de dados

Digamos que a partir do conjunto de dados da Figura 1 seja necessário totalizar a quantidade de acidentes por sexo para cada bairro. O resultado pode ser visto na Figura 2.

Figura 2 - Exemplo de Pivot Table

Utilizando a função de agregação SUM() em conjunto com a expressão CASE obtemos o resultado da Pivot Table:

terça-feira, junho 18, 2013

Configuração de Layers WMS do Mapserver no Leaflet

Aqui temos um exemplo de como configurar a biblioteca Leaflet com algumas camadas WMS do Mapserver.

Configuração do Mapfile:


Configuração da aplicação com o Leaflet:


Resultado:


quinta-feira, maio 30, 2013

Script para criação de mapas de declividade no GRASS

O script a seguir cria um mapa de declividade a partir de um Modelo Digital de Terreno, de acordo com classificação proposta por Lepsch (1991), descrita na Tabela 1.

Classe de Declividade  Porcentagem
Plano 0 - 2
Suave Ondulado  2 - 5
Moderadamente Ondulado 5 - 10
Ondulado 10 - 15
Forte Ondulado 15 - 45
Montanhoso 45 - 70
Escarpado > 70
Tabela 1 - Classes de declividade (LEPSH, 1991)

Para utilizar o script é necessário fazer o seu download (salve-o na pasta home, por exemplo) e lhe dar permissões de execução através do comando abaixo:
$ sudo chmod +x declividade.sh

Em seguida execute o comando dentro de uma sessão do GRASS:



Resultado:


REFERÊNCIAS:


LEPSCH, I. F. Manual para levantamento utilitário do meio físico e classificação de terras no sistema de capacidade de uso. Campinas : Sociedade Brasileira de Ciência do Solo, 1991.

sexta-feira, maio 24, 2013

Python: Geocodificação com a biblioteca pygeocoder

A biblioteca pygeocoder para a linguagem Python é uma mão na roda para quem precisa geocodificar com da API do Google. Com ela é possível encontrar as coordenadas de um determinado endereço, ou um endereço a partir de coordenadas conhecidas (x,y), processo conhecido como geocodificação reversa.

Vejamos como instalar e utilizar esta biblioteca:

1 - Instalação do Pip, que é um sistema de gerenciamento, usado para instalar e gerenciar pacotes de software escritos na linguagem de programação Python:
$ sudo apt-get install python-pip
2 - Instalação da biblioteca requests (caso seja necessário):
$ sudo pip install requests
3 - Instalação da biblioteca pygeocoder:
$ sudo pip install pygeocoder

4 - Obtendo as coordenadas a partir de um endereço:
from pygeocoder import Geocoder
endereco = Geocoder.geocode("Rua Violeta Formiga, 80, João Pessoa")
print(endereco[0].coordinates)
>>> (-7.0821068, -34.8407296)
print(endereco[0])
>>> Rua Violeta Formiga, 80 - Aeroclube, João Pessoa - Paraíba, Brazil

5 - Obtendo um endereço a partir das coordenadas:
coordenadas = Geocoder.reverse_geocode(-7.134660, -34.873325)
print(coordenadas[0])
>>> Avenida Primeiro de Maio, 792-866 - Jaguaribe, João Pessoa - Paraíba, 58015-430, Brazil

quarta-feira, fevereiro 27, 2013

Georreferenciamento de dados vetoriais usando o R e o PostGIS

Quem já trabalhou com o ArcGIS provavelmente já deve ter utilizado a extensão Spatial Adjustement que permite o ajuste de bases vetoriais distintas a partir de pontos de controle (conhecido como georreferenciamento de vetores). Neste tutorial irei apresentar uma solução semelhante utilizando a função ST_Affine do PostGIS e o software estatístico R.

Na Figura 1 temos duas camadas vetoriais, a de cor vermelha teve problemas no seu georreferenciamento e será ajustada a partir da base de cor verde. Para isso, primeiro é necessário  importar os shapefiles para um banco de dados geográfico e depois visualizar as tabelas criadas no QGIS:

Figura 1 - Bases cadastrais levantadas por empresas diferentes
Devem ser criadadas duas camadas vetoriais do tipo ponto no BDG onde foram importados os shapefiles. Observa-se na Figura 2 que a localização dos pontos vermelhos correspondem aos pontos verdes (origem -> destino).

Figura 2 - Pontos de controle criados
Em  seguida, em uma sessão no R via terminal deve-se digitar os seguintes comandos:
#carregando a biblioteca e o driver do PostgreSQL
library(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
#conexão com o BD
con <- dbConnect(drv, dbname="cadastro", 
                 user="marcello", 
                 pass="<minha_senha>")
#query 1 - coordenadas x,y dos pontos de destino
pts_ok <- data.matrix(dbGetQuery(con, 
                "SELECT ST_X(geom) AS x,
                 ST_Y(geom) AS y 
                 FROM pontos_ok"))
#query 2 - coordenadas dos pontos de origem
pts_err <- data.matrix(dbGetQuery(con, 
                "SELECT ST_X(geom) AS x,  
                 ST_Y(geom) AS y 
                 FROM pontos_errados"))
#regressão linear: modele pts_ok 
#como função estatística de pts_err 
parameters <- lm(pts_ok ~ pts_err)
#visualizando a matriz transposta dos coeficientes
t(coef(parameters))

Como resultado, teremos os coeficientes da equação que lineariza os pontos com as coordenadas erradas (pts_err) em função dos pontos de referência (pts_ok).
 (Intercept)  pts_errx  pts_erry
x   1312943.9 1.0138267 -0.143060
y   -163870.4 0.1389882  1.013313
Tais coeficientes são os parâmetros de entrada da função ST_Affine:
Formato de saída no R:
   | xoff a b |
   | yoff d e |

Formato de entrada no PostGIS:
 ST_Affine(geom, a, b, d, e, xoff, yoff)

Por último, são executadas as seguintes instruções no BDG:
--criação de uma cópia da tabela errada:
CREATE TABLE lotes_corrigidos AS
SELECT * FROM lotes_errados;

--em seguida o georreferenciamento dos lotes:
UPDATE lotes_corrigidos
SET geom =  
ST_Affine(geom, 
  1.0138267, -0.143060, 
  0.1389882, 1.013313, 
  1312943.9, -163870.4);

Finalizando, a Figura 3 mostra o resultado da base corrigida, o resultado foi satisfatório considerando a quantidade de pontos utilizada:

Figura 3 - Resultado do georreferenciamento (lotes_corrigidos)

terça-feira, fevereiro 19, 2013

PostGIS: Triggers e Procedures (Parte 2)

Complementando o post anterior, imagine o seguinte cenário: um mapa que mostre de forma esquemática, adutoras que serão projetadas para abastecer alguns municípios. Neste caso o objetivo é ter uma ideia dos comprimentos das adutoras (representados pela distância entre as sedes municipais), quantidade de municípios abastecidos e o nome dos mesmos.
CREATE TABLE adutoras (
 gid serial PRIMARY KEY,
 nome_adutora varchar(50),
 -- campo alimentado pela trigger
 comp_trecho_km numeric(10,3),
 -- campo alimentado pela trigger
 qtde_municipios_abast int,
 -- campo alimentado pela trigger
 municipios_abastecidos varchar(400)
 );

-- adição do campo geom
SELECT AddGeometryColumn (
 'public',
 'adutoras',
 'geom',
 '4291', --Lat/Long - Datum SAD69
 'LINESTRING',
 2
 );

-- Procedure
CREATE OR REPLACE FUNCTION pipeline_geometry_field()
RETURNS trigger AS
$$
BEGIN
SELECT string_agg(municipios.nome,', ')
INTO NEW.municipios_abastecidos
FROM municipios
WHERE ST_Intersects(NEW.geom, municipios.geom);

SELECT COUNT(municipios.*) 
INTO NEW.qtde_municipios_abast
FROM municipios
WHERE ST_Intersects(NEW.geom, municipios.geom);

NEW.comp_trecho_km:=ST_Length(Geography((NEW.geom))/1000);

RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

-- Trigger
CREATE TRIGGER fill_pipeline_geometry_field
BEFORE INSERT OR UPDATE ON adutoras
FOR EACH ROW EXECUTE PROCEDURE pipeline_geometry_field();

O vídeo a seguir mostra a implementação do código acima, a partir da edição da tabela adutora no QGIS, observa-se o preenchimento automático dos campos após o salvamento da feição no Banco de Dados:

domingo, fevereiro 17, 2013

PostGIS: Triggers e Procedures (Parte 1)

Quem já estudou normalização em Banco de Dados sabe que campos calculados devem ser eliminados por ferirem a terceira forma normal, no entanto, quando trabalhamos com SIG muitas vezes precisamos de campos como: área, perímetro, centróide, dentre outras medidas, calculadas a partir das geometrias das feições.

Porém, tais campos devem possuir um mecanismo que possibilite o seu cálculo de forma automatizada, tanto para novas feições, quanto para mudanças na forma original da geometria, através da edição da base. Uma forma de implementar tal comportamento em uma tabela espacial com campos calculados, é através de triggers e procedures.

Aqui temos um exemplo uma stored procedure e de uma trigger que calcula os valores de área (area_m2) e perímetro (perimetro_m) da tabela lote, a partir da geometria, armazenada no campo geom:

--Criação dos campos que serão calculados (caso não existam ainda)
ALTER TABLE lotes ADD area_m2 numeric(10,3);
ALTER TABLE lotes ADD perimetro_m numeric(10,3);

--Atualização dos valores dos campos calculados
UPDATE lotes SET area_m2 = ST_Area(geom);
UPDATE lotes SET perimetro_m = ST_Perimeter(geom);

-----------------------------
--Criação da Stored Procedure
-----------------------------
CREATE OR REPLACE FUNCTION calculate_geometry_fields()
RETURNS trigger AS
$$
BEGIN
NEW.area_m2:=ST_Area(NEW.geom);
NEW.perimetro_m:=ST_Perimeter(NEW.geom);
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

--------------------
--Criação da Trigger
--------------------
CREATE TRIGGER fill_geometry_fields
BEFORE INSERT OR UPDATE ON lotes
FOR EACH ROW EXECUTE PROCEDURE calculate_geometry_fields();

segunda-feira, fevereiro 11, 2013

Como importar vários arquivos para o GRASS via Terminal

Este laço deve ser aplicado dento do diretório que contém os dados que serão importados para o GRASS:
for i in *.<extensao>; do r.in.gdal -o in=$i out=`basename $i`; done
Onde <extensao> é a extensão dos arquivos raster do diretório atual.

quarta-feira, fevereiro 06, 2013

PostGIS: extração de medidas em tabelas com coordenadas geográficas

É possível obter valores de área, comprimentro, distância e perímetro em tabelas ondes os dados estão em lat/long, através da função Geography(). Seguem alguns exemplos:

quinta-feira, janeiro 24, 2013

Run Time Substitution no Mapserver

(Obs.: Atualizado para a versão 6.4 do Mapserver)

1- INTRODUÇÃO


Desde a versão 4.0, o Mapserver apresenta uma funcionalidade chamada “Run Time Substitution”, que é muito interessante para destacar determinadas feições do mapa que está sendo exibido no navegador.

O seu funcionamento é bastante simples e não requer conhecimentos sobre programação MapScript, sendo necessário apenas fazer alguns ajustes no arquivo mapfile e inserir os parâmetros na url que indicarão qual ou quais feições devem ser destacadas.

Para demonstrar a utilização desse recurso, imagine o seguinte cenário: um aplicativo WebGIS exibe o mapa estadual e após a realização de uma consulta, deve-se mostrar o município que foi selecionado com uma cor diferente das demais feições da camada. Este é um exemplo simples de como podemos utilizar o  Run Time Substitution.

Neste tutorial, será demonstrado como montar um mapfile com este recurso, utilizando dados do estado do Ceará. O ambiente de desenvolvimento utilizado será o Ubuntu 12.04. No entanto, nada impede que o desenvolvedor realize este tutorial em outro sistema operacional, desde que sejam realizadas as devidas modificações dos paths das pastas e da url.

2- DOWNLOADS DOS DADOS E CRIAÇÃO DAS PASTAS:


Faça o download dos dados neste link.

Em seguida cria-se uma pasta com o nome ce na pasta raiz do seu servidor Web, no meu caso ela fica em /var/www/html. Descompacte a pasta contendo os dados dentro da pasta “ce” criada.

3- CRIAÇÃO DO ARQUIVO MAPFILE:


Utilizando o editor de texto qualquer, crie dentro da pasta ce o arquivo ceara.map, com o seguinte conteúdo:


Para testar o mapfile criado,  abra o browser e digite a seguinte url:


Deverá aparecer uma imagem no navegador semelhante a da Figura 1:

Figura 1 - Teste do mapfile criado

4- PREPARANDO O RUN TIME SUBSTITUTION NO MAPFILE:


Adicione a camada que terá o recurso de substituição em tempo de execução, para isso, altere o mapfile anterior, adicionando antes da última linha (Fim do mapfile) as instruções a seguir:


Temos agora alguns novos elementos, primeiro, dentro do objeto VALIDATION aparece uma regra de validação (construída com o uso de expressões regulares), que é necessária para o funcionamento correto deste recurso, pois caso seja passado algum valor na url que não seja numérico e que não possua de um a três dígitos, não será exibido nada de diferente no mapa. O nome da regra deve ser o  mesmo nome do campo, neste caso idmun é uma coluna que contém valores incrementais de 1 a 184. Ou seja, cada município pode ser representado por um código deste campo.

O outro novo elemento é o objeto FILTER, nele deve-se especificar as feições que serão exibidas no mapa, através de uma expressão, no nosso caso, a expressão contém apenas o nome da coluna id_mun entre os caracteres de máscara ‘%’. Mais detalhes sobre como utilizar os filtros podem ser encontrados na documentação do Mapserver.

5- RESULTADO:


Para testar o funcionamento deste recurso, adicionamos mais uma variável na url, contendo o nome da coluna que definimos em FILTER (idmun), da seguinte forma:


Se não houve nenhum erro de digitação, deverá ser exibido o mapa anterior com a feição com o idmun igual a 63 destacado, como mostra a Figura 2.

Figura 2 - Resultado do Run Time Substitution

Variando os valores de 1 a 184 vemos que o recurso funciona perfeitamente, destacando outras feições. Agora é usar a criatividade para desenvolver as aplicações Mapserver explorando este recurso. Uma sugestão é combiná-lo com a variável mapext na url onde são passados as coordenadas do retângulo envolvente da feição selecionada, da seguinte forma: &mapext=xmin+ymin+xmax+ymax.

6- SUGESTÕES DE LEITURA:

sexta-feira, janeiro 18, 2013

MapServer e PostGIS: procedimentos para uma conexão segura

A conexão entre  o MapServer e o PostGIS é feita através de uma string de conexão, permitindo que qualquer pessoa que tenha acesso ao Mapfile possa ver os parâmetros de acesso ao Banco de Dados, imaginem isto nas mãos de uma pessoa mal intencionada. A mesma poderia realizar qualquer ação no BD, desde de alterar registros, ou até mesmo apagar todos os dados.

Para impedir que isso aconteça, pode ser criada uma role de acesso com permissão apenas de leitura, desta forma não haveria problema da string de conexão cair em mãos erradas.

Para criar a regra, temos que acessar o Banco de Dados da aplicação e digitar as seguintes instruções SQL:
-- Criando o usuário webgis:
CREATE USER webgis WITH PASSWORD '--123456--';
-- Removendo todos os privilégios 
-- deste usuário no esquema public:
REVOKE ALL PRIVILEGES ON SCHEMA public FROM webgis;
-- Dando permissão apenas de leitura (SELECT) 
-- no esquema public a este usuário:
GRANT SELECT ON ALL TABLES IN SCHEMA public TO webgis;

OBS: em versões mais antigas do PostgreSQL não é possível definir uma role para todo o esquema, sendo necessário setar tabela por tabela as permissões do usuário criado.

Para que uma mesma string de conexão possa ser aproveitada em mais de uma camada, pode ser utilizado o recurso INCLUDE no mapfile que contém o(s) layer(s):

LAYER
  NAME 'rodovias'
  TYPE LINE
  STATUS DEFAULT
  CONNECTIONTYPE postgis
  #--- Include com os parâmetros da conexão ----
  INCLUDE 'conn.map'

  DATA 'geom FROM rodovias USING UNIQUE gid USING srid=29185'

    CLASS
      NAME 'Rodovias' 
        STYLE
          WIDTH 1.96 
          COLOR 255 0 0
        END
    END
END

e no conteúdo do arquivo conn.map, colocamos a string de conexão:
CONNECTION "dbname='atlas' host=localhost 
         port=5432 user='webgis' password='--123456--'"

Caso seja do interesse do desenvolvedor, a string de conexão também pode ser criptografada com o utilitário msencrypt, aumentando ainda mais a segurança:

Pelo Terminal, entre na pasta da aplicação e digite:
msencrypt -keygen mykey.txt
Em seguida criptografe a string de conexão:
msencrypt -key mykey.txt "dbname='atlas' host=localhost port=5432 user='webgis' password='--123456--'"

#--- Resultado mostrado no Terminal (string criptografada) ---
93E8501D65EA2F92A5C7E6E1412F834F8652B7727F6464087F97B0C6FB5CE23369F5DD2A301A94CB857E61D3EE2F68A03CE0DE2953F13F07DD77159274563E83D74942FB7861534C
No início do mapfile, é definido o objeto CONFIG MS_ENCRYPTION_KEY:
MAP
  NAME "Exemplo"
  EXTENT 258948 9180428 301662 9206961  
  SIZE 600 600
  UNITS meters
  # path até o arquivo mykey.txt, gerado anteriormente:
  CONFIG MS_ENCRYPTION_KEY "mykey.txt"
  .
  .
  .


Por último, abra o arquivo conn.map e substitua a string atual pela criptografada (sem quebras de linha):
CONNECTION "{
             93E8501D65EA2F92A5C7E6E1412F834F8652B7727F64640
             87F97B0C6FB5CE23369F5DD2A301A94CB857E61D3EE2F68
             A03CE0DE2953F13F07DD77159274563E83D74942FB7861534C
            }"

Mesmo (sendo pouco provável) que a string possa ser descriptografada, ainda assim o acesso ao Banco de Dados é realizado por uma role que só consegue realizar SELECT. Desta forma estamos garantindo um acesso "blindado" ao BD.