Django Topology

Olá pessoal!

Aqui na SIGMA sempre estamos desenvolvendo ferramentas úteis para nós e que talvez também sejam úteis para outras pessoas.

Nossa ideia principal, é contribuir um pouco com esse enorme ecossistema Python/Django existente. Como já disseram, estamos sobre os ombros de gigantes.

Bem, desenvolvemos o Django Topology com o objetivo de simplificar a validação de dados geométricos/geográficos que encontramos em nosso dia a dia.

É muito comum, por exemplo, ter de validar a entrada de um polígono e precisamos garantir que ele esteja dentro de outro polígono. Ou garantir que este polígono específico não esteja sobrepondo outro polígono de uma mesma classe.

Para isso desenvolvemos o Django Topology. Através dele você consegue configurar suas validações dentro do banco de dados e executá-las de forma simples.

O fluxo é simples e o pacote já conta com três validações:

  • must be contained – garante que o modelo A deve estar contido no modelo B;
  • must not overlap – garante que o modelo A não pode sobrepor nenhum outro registro em A;
  • must not overlap with – garante que o modelo A não pode sobrepor o modelo B;

O pacote é facilmente extensível e você desenvolver suas próprias validações topológicas.

Um exemplo simples:

        rule = Rule(
            name='regra de validação 1',
            description='A deve estar contido em B',
            message='deve estar contido',
            method='topology.rules.must_be_contained'
        )
        rule.save()
        topology_rule = TopologyRule(
            content_type_a=ContentType.objects.get(app_label='seuapp', model='item'),
            content_type_b=ContentType.objects.get(app_label='seuapp', model='container'),
            geom_field_b='geom',
            rule=rule
        )
        topology_rule.save()

Até aqui, definimos nossa regra topológica, de que A (qualquer instância do modelo Item) deve estar contida em B (Container).

Veja como realizar a validação:

        item_a = Item(geom=unit_polygon(Point(x=0.0, y=0.0, srid=4326)))
        item_a.save()
        container = Container(geom=unit_polygon(Point(x=0.0, y=0.0, srid=4326), size=3))
        container.save()

        errors = topology_rule.validate(item_a)
        len(errors)
>>> 3

No exemplo acima, calculamos os erros diretamente pela regra topológica (TopologyRule) e não foi encontrado nenhum erro.

Os erros gerados pelo TopologyRule não são persistidos no banco de dados, ficando a cargo do desenvolvedor a determinar o melhor momento para tal. As vezes nem será necessário, como por exemplo, em uma validação de formulário Django.

Também desenvolvemos um análogo ao TopologyChecker do QGIS e ele tem o mesmo nome. Sua função é executar todas as validações associadas a um determinado modelo, de uma vez, e persisti-las (ou não).

Veja como usá-lo:

        # definindo as regras
        rule1 = Rule(
            name='A não deve sobrepor A',
            description='A não deve sobrepor A',
            message='sobrepõe',
            method='topology.rules.must_not_overlap'
        )
        rule1.save()
        rule2 = Rule(
            name='A não deve sobrepor B',
            description='A não deve sobrepor B',
            message='sobrepõe',
            method='topology.rules.must_not_overlap_with'
        )
        rule2.save()
        topology_rule1 = TopologyRule(
            content_type_a=ContentType.objects.get(app_label='seuapp', model='item'),
            rule=rule1
        )
        topology_rule1.save()
        topology_rule2 = TopologyRule(
            content_type_a=ContentType.objects.get(app_label='seuapp', model='item'),
            content_type_b=ContentType.objects.get(app_label='seuapp', model='container'),
            geom_field_b='geom',
            rule=rule2
        )
        topology_rule2.save()

        item1 = Item(geom=unit_polygon(Point(x=0.0, y=0.0, srid=4326)))
        item1.save()
        item2 = Item(geom=unit_polygon(Point(x=0.0, y=0.0, srid=4326)))
        item2.save()
        container = Container(geom=unit_polygon(Point(x=0.0, y=0.0, srid=4326), size=2))
        container.save()

        # até aqui, criamos nossas regras e os registros de item e container

        topo_checker = TopologyChecker()

        errors = topo_checker.validate_all(Item)

O TopologyChecker retorna um dicionário, usando como chave o nome da validação executada e uma lista associada, com N erros detectados. No caso acima, o topologychecker encontrou 4 erros:

  • item 1 sobrepõe item 2;
  • item 2 sobrepõe item 1;
  • item 1 sobrepõe Container 1;
  • item 2 sobrepõe COntainer 1;

Estamos usando o Django Topology em produção no Geoadmin um produto que trabalha intensivamente com dados geográficos.

Você pode extender o mesmo com suas próprias validações. Basta criar um método com a seguinte assinatura:

def minha_validacao(rule, feature, **kwargs):
    # sua validacao aqui
    # deve retornar uma lista de TopologyError (sem salvar no banco)
    if feature.geom.intersects(outra_geometria):
        return [TopologyError()]

    return []

Com este método pronto, você só precisa criar uma Rule, apontando o atributo method para o caminmho qualificado da sua função:

rule = Rule(
    name='name'
    method='foo.bar.minha_validacao
)

Quer ajudar? Estamos aí, confere o repositório e bora lá.

SIG com Python

Este é um tema vasto e pretendo falar sobre alguns conceitos como: Datum, Sistemas de Coordenadas, Projeção, Sistema de Referência e conceitos de SIG (Sistemas de Informações Geográficas).
Não conseguiremos cobrir os conceitos de operações espaciais, porém na demonstração isto será ilustrado em linhas gerais.

Este é um artigo derivado do screencast SIG com Python, disponível no YouTube.

O ambiente em que executamos esta aplicação está disponível no servidor de código fonte da sigma em: https://gitlab.sigmageosistemas.com.br/screencasts/gis-hands_on, neste repositório você tem o Dockerfile e no repositório https://gitlab.sigmageosistemas.com.br/dev/dockerize você encontra instruções de como buildar e montar esta imagem.

Localização e Medições

Localizar e Medir são uma necessidade inerente ao ser humano desde as sociedades mais antigas.

Com o passar dos séculos, foi preciso definir medidas mais precisas e padronizá-las permitindo às pessoas em qualquer local do planeta, entender e realizar medições, para estimar distancias, áreas e locais, definindo precisamente as fronteiras de um pais, estado, cidade, fazendas e terrenos.

A Geodésia é a área de conhecimento que estuda e aprimora os métodos de medição do planeta.

O planeta terra tem forma similar à uma batata, sendo sua forma matemática mais aproximada, uma elipse, sendo assim, o primeiro passo para calcular as medidas do planeta é a definição de uma elipsoide de referência.

Devido a deformidade do planeta, a forma eliptica se encaixa melhor em variadas regiões, conforme alteramos os parâmetros de tamanho e posição deste em relação ao eixo da Terra. A estes parâmetros que definimos para o elipse chamamos de Datum.

Com base no Datum, podemos determinar em radianos o posicionamento de algo no globo terrestre, ou até mesmo em métros.
Porém quando precisamos representar esta informação em um mapa, em outras palavras, precisamos transformar uma bola em uma folha de papel, é necessário projetar do dado geográfico, projeção é um modelo matemático com base no datum e sistemas de coordenadas, que tranforma as coordenadas geográficas em um plano cartesiano.

A projeção tem diversos tipos:

Cilindricas (Normal, Transversa, Obliqua), Planas (Polar, Equatorial, Obliqua), além de outros tipos como Gnomonica, Estereográfica e etc.

Cada uma delas é ideal para determinadas regiões ou cenários de uso.

O que é um Sistema de Informação Geográfica (SIG)?

É um sistema computacional que utiliza dados de localização geográfica como: coordenadas ou endereços, em conjunto com algoritmos que consumam estes dados para contruir informações.

Não necessariamente um sistema GIS precisa exibir um mapa, ele pode por exemplo informar o tempo estimado para uma entrega ser concluída ou enviar um SMS indicando que seu bairro passará por uma instabilidade elétrica.

Checklist

Nesta seção apresentamos um checklist de como iniciar a definição de seu SIG. São perguntas importantes, que devem ser respondidas antes de sua construção. É uma etapa crucial, para que o SIG, atenda as necessidades da sua organização.

Qual é o sistema de referência de seu dado geográfico?

Por mais que para os desenvolvedores de sistema, este seja uma assunto muito complexo, é extremamente importante ter o conhecimento sobre alguns detalhes do dado geográfico utilizado.

A parte mais importante à se pensar ao criar um sistema de informação geográfica é qual sistema de referência vamos utilizar. Mas como escolher?

Respondendo as questões:

  • Qual abrangência da área de trabalho, cidade, estado, países?
  • Qual principal requisito: precisão de área e comprimento ou precisão de posicionamento?

A resposta destas duas questões é geralmente respondida pela equipe cartográfica de seu cliente ou por geográfos, porém é importante compreender os motivadores destas escolhas.

Qual a forma de obtenção das coordenadas?

Para sistemas que requerem precisão é necessário coletar as informações geográficas com equipamentos avançados, que possuam precisão métrica (ou submetrica) e permitam seu pós processamento, aumentando ainda mais sua precisão.

Para casos em que isso não é necessário, somente as coordenadas gps de um smartphone são suficientes.

Mas tenha em mente que toda iteração (ou interação) com o mapa para criar dados geográficos à mão livre é imprecisa, pois o nível de zoom e a referência pixels para coordenada geográfica prejudicam a precisão.

Qual é a informação que será produzida com este dado geográfico?

É muito importante pensar nisso quando vai contruir um sistema, pois ter uma mapa em sua aplicação a enriquece bastante, mas se não há uma utilidade funcional isso pode acabar tornando-se um grande problema.

Então é crucial pensar no resultado final, ou na informação que queremos produzir e mostrar aos nossos usuários.

Demo

A demonstração vai exibir código que permite importar dados de um arquivo shp, em seguida como apresentá-los no mapa e por fim sua consulta.

Shapefile: Formato binário de arquivos espaciais da ESRI, que se tornou bastante popular.
PostGIS: Banco de dados geográfico.
GEOS: Biblioteca de Operações Espaciais e Conversões;
TileStache: Servidor GIS de Vector Tiles;
Django TileStache: APP Django que cria um endpoint tilestache para suas entidades geográficas.
Django Rest Framework: Permite a criação de endpoints rest para seus django models.
Django Rest Framework GIS: Permite a serialização de Atributos geométricos e operações espaciais através do DRF endpoint;

Referências:

UFABC Flavia Feitosa: https://flaviafeitosa.files.wordpress.com/2015/06/02a_sistreferencia-compressed.pdf
Geodésia: https://pt.wikipedia.org/wiki/Geod%C3%A9sia
Curso de PostGIS Sigma: https://github.com/sigma-geosistemas/sigma.universidade.postgis/wiki/aula02
imagem qgis: https://flic.kr/p/UGGiGu

Metodologia para cartografia de larga escala

Boa noite pessoal!

Hoje vamos falar um pouco sobre a metodologia da SIGMA referente a cartografia de larga escala.

Bem, a definição de larga escala pode variar de projeto para projeto, mas geralmente estamos falando de áreas com milhares de objetos geográficos (ou feições) em uma escala de até 1:10.000.

Vou comentar primeiramente da nossa experiência e logo depois irei comentar das ferramentas que desenvolvemos para auxiliar os analistas de geoprocessamento e a gerência a ter uma visão completa do projeto.

Nossa experiência

A SIGMA Geosistemas já executou diversos projetos que podem ser considerados como cartografia de larga escala. Em uma conta rápida, estimo aproximadamente entre 60 e 70 mil km2 mapeados, utilizando apenas tecnologias livres, distribuídos entre os diversos projetos executados.

Uma breve descrição sobre nosso stack tecnológico:

  • PostgreSQL + PostGIS;
  • pgpool;
  • QGIS (diversas versões);
  • cartobash;
  • X9 (monitor de progresso);

O PostgreSQL com o PostGIS, é sem dúvida, o banco de dados geoespacial mais capaz do mercado. Ele é nossa principal arma para este tipo de projeto, pois é um banco de dados:

  1. Robusto;
  2. Cheio de funcionalidades importantes para análise espacial;
  3. Permite centenas de conexões simultâneas, sem problemas;
  4. Fácil de configurar e manter;

Junto ao PostgreSQL, para ajudar a manter estas centenas de conexões simultâneas (cada usuário pode abrir mais de uma conexão ao banco), usamos o pgpool. Ele é responsável por criar um pool de conexões, sem termos a necessidade de recriamos cada conexão a todo momento. Isto nos traz robustez e aumenta o desempenho.

Em cima disto tudo, a estrela: QGIS, de preferência uma versão recente.

O cartobash e o X9 são ferramentas abertas que a SIGMA desenvolveu para auxiliar nesta tarefa.

O cartobash é uma ferramenta escrita basicamente em shell script, que automatiza diversas partes da construção de novos bancos de dados, configuração de logging, backups e issues.

Além disso, o cartobash gerencia versões padrões de projetos QGIS, permitindo que cada analista gere seu arquivo de projeto, insira rapidamente sua senha e configure as diversas camadas daquele projeto.

O X9 é um experimento escrito em Python e Django para ajudar a monitorar o que está sendo feito pelos analistas, em tempo real.

Ele consulta a base de dados e a base de logs, para determinar qual é o total de edições realizadas naquele dia, qual é a porcentagem de progresso do projeto, entre outras métricas interessantes.

Descrita as ferramentas, passamos para a metodologia!

Metodologia

Em temos gerais, passamos pelas seguintes etapas:

  1. Definição da abrangência geográfica do projeto;
  2. Definição do modelo de dados;
  3. Construção do banco de dados com o cartobash;
  4. Setup de logging, issues, áreas de trabalho e funcionalidades de validação automatizadas;
  5. Construção do projeto padrão QGIS;
  6. Delegação de permissão para os analistas;
  7. Mãos a obra!isto

Para o início de todos os projetos, o primeiro passo é determinar seu modelo de dados e sua abrangência geográfica.

De posse dessas informações, já saberemos o quão complexo será a construção e digitalização dessa base de dados.

Neste ponto, com o modelo de dados principal, tabelas relacionados (ou auxiliares) prontas, configuramos o logging, issues e áreas de trabalho.
isto
Esta etapa é (e deve ser) automatizada. Tudo isto é feito pelo cartobash. Dividimos o projeto em sub-áreas, utilizando algumas funcionalidades do PostGIS e delegamos as mesmas para os analistas.

As issues também são configuradas nesta etapa. As issues ou não-conformidades são dados geográficos que podem ser utilizados pelos analistas e revisores, para marcar áreas que não estejam de acordo com o padrão de qualidade esperado.

Dependendo do tipo de projeto, configuramos as isto validações automatizadas, como regras topológicas, executadas a cada minuto, podendo ser visualizadas pelos analistas em tempo real.

UFA! O cartobash nos ajuda até aí, então é bem fácil de realizar isso tudo. Basta rodar um comando bash e correr para o abraço.

A parte complicada, é construção do projeto do QGIS. O QGIS permite a construção de formulários customizados, com regras avançadas de relacionamento entre tabelas.

Por exemplo, um tipo de feição possui um campo chamado CLASSE, que só pode ter um dos valores: A, B ou C. Usando as ferramentas do QGIS permitem que você configure e limite as opções do analista, apenas a estas três.

Este é um exemplo simples, mas a partir desta configuração, o projeto padrão é disseminado entre os analistas, que inserem seu próprio usuário e senha do banco de dados.

A partir deste momento, devemos por a mão na massa.

Divisão em sub-áreas

Existe um desafio complexo ao trabalhar com projetos massivos como os que trabalhamos. A sensação de progresso experimentada pelos analistas é bastante pequena, quando não delegamos áreas menores para seus trabalhos.

Caso eles tenham liberdade para escolher as áreas de trabalho, sem uma limitação menor, a sensação de avanço do trabalho é pequena e acabam se desmotivando.

O segredo que permitiu aumentar a produtividade e aumentar a sensação de progresso entre os colaboradores foi a divisão do projeto em áreas menores, assinalando as mesmas a cada analista.

Apesar de funcionar, pode trazer alguns problemas, como a eventual correção de divergências entre as grades, mas em nossa experiência, essas correções são pequenas – fazendo esta estratégia valer a pena.

Conclusão

Neste post tentamos trazer para vocês um pouco nossa experiência com projetos de cartografia de larga escala.

Qual é a sua experiência? Comente conosco!

E você? tem algum projeto de cartografia de larga escala e precisa de ajuda? Conte conosco.

Um abraço!

Conexão QGIS – PostGIS

Hoje vamos falar sobre uma ferramenta importante do QGIS, usada para conexão com banco de dados PostgreSQL/PostGIS.

Com esta ferramenta você poderá gerenciar seus bancos de dados, e as principais formas de interação são:

  • Importar Shapefile para o banco de dados;
  • Exportar uma tabela do banco de dados para diversos formatos;
  • Executar queries complexas e carregá-las como camada diretamente no QGIS;

Para criar a conexão devemos acessar o menu Camada > Adicionar Camada > PostGIS.

Será aberta a tela a seguir:

Adicionar Camada Postgis

Ao clicar em Novo será aberta a tela de configuração de conexão onde deverão ser incluídos os dados de conexão. O QGIS suporta a conexão tanto com servidores locais, quanto na rede interna, até mesmo na internet.

Veja abaixo a tela de conexão com o banco de dados.

Configuração de conexão com o banco

Após inserir os dados você poderá clicar em Testar conexão para verificar se os dados inseridos estão corretos e clicar em OK para salvar sua conexão.

Se tudo estiver correto ao clicar no botão Conectar serão listadas todas as tabelas que possuem colunas geométricas.

A partir daí você poderá adicionar as camadas aos seus projetos, porém esta funcionalidade ainda não permite o gerenciamento de Banco de Dados, ela é o primeiro passo para gerenciá-lo.

Lista de Tabelas Postgis

Para acessar a ferramenta de gerenciamento de Banco de dados você deverá acessar o menu Banco de Dados > Gerenciador BD > Gerenciador BD.

Ao clicar você verá a tela abaixo, note que se expandir o menu do PostGIS irá ver a conexão criada.

Tela Gerenciado Banco de Dados

Você poderá navegar entre as tabelas de seu banco de dados, note que no nome de cada tabela existe um ícone mostrando qual é o tipo geométrico da tabela. Caso ela não possa geometria, o QGIS utiliza um outro ícone para renderizá-la.

Nas abas Info, Tabela e Pré-visualizar você poderá ter acesso rápido aos dados do banco sem a necessidade de carregar a camada em seu projeto.

Pré-visualização de camadas

Existem três ferramentas que são muito úteis para a manipulação dos dados no PostGIS.

Ferramentas

São elas:

  • Janela SQL

Janela SQL

Através da Janela SQL você poderá utilizar qualquer query para consultar seu banco de dados, inclusive utilizando funções do Postgis.

SELECT
id,
ST_AsText(geometria) as geometria.
ST_IsValidReason(geometria) as tipo_erro
FROM uso_solo
WHERE ST_IsValid(geometria_ = FALSE)

No exemplo o objetivo é listar os polígonos com geometria invalida para que possam ser corrigidos.

Foram utilizadas as funções:

ST_GeomFromText para retornar as coordenadas em texto;

ST_IsValidReason para mostrar qual o erro que gerou a geometria invalida e

ST_IsValid para listar somente as geometrias inválidas.

Além de listar estes polígonos é possível carregar o resultado como uma camada, basta marcar a opção Carregar como uma nova camada, para isto é necessário que exista no resultado de sua query uma coluna com um valor único e uma coluna com o valor geométrico, selecione os campos e clique no botão Carregar agora!, e uma nova camada será carregada em seu projeto.

Abaixo figura da camada carregada com o erro encontrado:

Camada carregada Qgis

  • Importar Camada/arquivo

Janela de Importação

Esta ferramenta importa um arquivo do tipo shapefile do QGIS diretamente para o PostGIS. Não é necessário criar a tabela previamente, será criada juntamente com as colunas e os tipos definidos no arquivo shapefile.

  • Exportar Camada/arquivo

Exportar Camada

Esta ferramenta faz o oposto da importação, com ela é possível exportar uma tabela do banco de dados para um arquivo shapefile ou em algum dos formatos suportados.

Quem trabalha com com geoprocessamento ou dados geográficos e quer conhecer um pouco mais do PostgreSQL/PostGIS esta é uma ferramenta incrível para começar, pois irá lhe poupar algumas horas de trabalho visualizando os resultados das queries direto no mapa.

Django TileStache

Nesta postagem iremos falar sobre mais um trabalho da SIGMA que disponibilizamos de maneira open-source. Desta vez iremos falar sobre o Django TileStache.

O TileStache é um servidor de tiles, escrito em Python. É um servidor bastante flexível, bastando uma configuração em JSON para que o mesmo funcione.

Ele é perfomático, mas a limitação dele de funcionar apenas com um arquivo de configuração estava nos incomodando.

O problema

Em algumas de nossas soluções, nossas camadas a serem servidas pelo TileStache são dinâmicas. Isto significa, que depois de determinado evento, precisarei servir novos dados através do TileStache.

Um exemplo claro: dentro do Geoadmin, quando um cliente novo se registra, precisamos servir as camadas que são dele. E isto necessita de uma nova configuração.

A solução

A solução para este problema tem duas partes. A primeira delas foi desenvolver um cadastro de camadas. Este cadastro de camadas já é preparado para funcionar com o Django REST Framework e nos permite cadastrar layers de forma arbitrária. Todos os tipos de providers suportados pelo TileStache são suportados, mas via REST, apenas quatro tipos, por agora:

  • External (classes externas);
  • Vector (qualquer fonte, PostGIS, Shapefile, Spatialite e JSON);
  • Mapnik;
  • Proxy;

Usar o cadastro de layers é bastante simples, veja só:

from django_tilestache.models import Layer

layer = Layer.objects.create(
    **{
        'name': 'foolayer'  # this is the tilestache layer name
        'provider': {

        },  # tilestache provider options
        '...' : 'foo' # all other options
    }
)

No exemplo acima, criamos uma layer com o nome de foolayer, mas não demonstramos as opções de provedor. Se você seguir o TileStache, qualquer layer será válida.

A outra parte da solução, consiste num servidor customizado do TileStache. Pegamos o servidor WSGI original e extendemos o mesmo para que de, tempos em tempos, ele faça um request para o servidor de comando e controle (neste caso, a aplicação Django que contém o django-tilestache instalado), que retorna a nova configuração.

Você pode, e deve, inclusive, estabelecer credenciais para isto. A configuração do TileStache contém informações sigilosas e não deve ser exposta diretamente para internet.

Views

Duas views iniciais foram desenvolvidas para suportar algumas questões de desenvolvimento aqui na SIGMA, são elas:

  1. TileStacheConfiguration – esta view específica retorna a configuração registrada do TileStache, em formato JSON. Este é o endpoint utilizado para que o TileStache remoto, consiga se atualizar.
  2. TileStacheTile – esta view renderiza tiles das camadas registradas, ou seja, caso você não queira, você pode usar esta view para servir seus tiles em seus projetos Django.

Instalação

pip install django-tilestache

Configuração

  1. Vá em seu settings.py do Django. Adicione django_tilestache nas INSTALLED_APPS.
  2. Rode o comando migrate para criar os modelos no seu banco de dados;
  3. Adicione as urls do django-tilestache dentro do das suas URLS. Este passo é opcional. Se você fizer isto, terá de usar a estrutura de URLS definida pelo app. Caso queira alterar esta estrutura, registre suas views manualmente;

Gostou?

O repositório está disponível em: https://gitlab.sigmageosistemas.com.br/dev/django-tilestache. Seja bem vindo e nos ajude na construção deste pacote.

Abraços

Nesta postagem iremos falar sobre mais um trabalho da SIGMA que disponibilizamos de maneira open-source. Desta vez iremos falar sobre o Django TileStache. O TileStache é um servidor de tiles, escrito em Python. É um servidor bastante flexível, bastando uma configuração em JSON para que o mesmo funcione. Ele é perfomático, mas a limitação dele