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.

segunda-feira, janeiro 14, 2013

R: Análise de dados pluviométricos com o hydroTSM

A biblioteca  HydroTSM - Hydrological time series plotting and extraction, amplia a versatilidade do  R no que diz respeito ao trabalho com dados hidrológicos, possibilitando diversas análises e criação de gráficos de séries temporais pluviométricas e fluviométricas.

Por exemplo, a partir de dados coletados diariamente de uma estação pluviométrica, podem ser gerados gráficos de linhas, boxplots e histogramas, em três diferentes escalas de tempo (diário, mensal e anual).

O exemplo abaixo foi aplicado para a série histórica do posto pluviométrico de També, na Bacia do Rio Gramame (PB), entre os anos de 1972 a 1987:

#carregando a biblioteca:
library(hydroTSM)
#carregando os dados do posto pluv.
# de també (bacia do Gramame)
tambe <- read.zoo(
  "/home/marcello/tambe.csv",
  format="%m/%d/%Y", #formato das datas no arquivo (mês/dia/ano)
  sep=";", #separador dos dados
  tz="GMT", #timezone
  header=TRUE
)
#Plotando o Gráfico
hydroplot(
  tambe, 
  var.type="Precipitation",
  pfreq = "dma" #dma = diário, mensal e anual
)

O resultado pode ser visto na Figura 1:  

Figura 1 - Saída do comando  hydroplot

Uma outra saída interessante é a criação de treemaps, como mostra o script abaixo, o resultado pode ser conferido na Figura 2:

#gerando dados mensais a partir das leituras diárias
dados_mensais <- daily2monthly(tambe, FUN=sum)
#criando a matriz com os dados mensais 
M.dados_mensais <- matrix(monthly, ncol=12, byrow=TRUE)
#colocando os "headers" na matriz
colnames(M.dados_mensais) <- month.abb
rownames(M.dados_mensais) <- unique(format(time(monthly), "%Y"))
#carregando a biblioteca lattice (necessário)
require(lattice)
#plotand os dados
matrixplot(
  M.dados_mensais,
  ColorRamp="Precipitation",
  main="Precipitação mensal no posto També (mm/mês)"
)

Figura 2 - Heatmap: Precipitação mensal/Ano

Sugestões de Leitura