Norma Cartográfica no QGIS – Alterar formulários de edição com PyQGIS

PT | EN

Enquanto preparava um projecto QGIS para leitura da estrutura de base de dados descrita nas novas Normas e Especificações Técnicas de Cartografia , comecei a configurar os formulários de edição das várias camadas de forma a:

  1. Bloquear a edição de campos só de leitura, como por exemplo um identificador.
  2. Configurar widgets adequados aos campos, que facilitem a vida do utilizador e evitem que cometa erros, como por exemplo campos com dadas e listas de valores fixos.

No fundo, o que procurava era qualquer coisa deste género:

Peek 2019-09-30 15-04_2

Antes de mais, é preciso dizer que o QGIS, quando lê uma tabela PostGreSQL/PostGIS, já faz um excelente trabalho a adivinhar, para cada campo, o tipo de widget a usar, assim  como as constraints a aplicar. O que é uma enorme ajuda. No entanto, alguns campos precisam de uma configuração extra.

Se se tratassem de meia-dúzia de camadas e campos, teria feito tudo de manualmente, mas ao fim da quinta camada, o meu Mantra começou a chamar por mim:

“Quando usas um computador, se estás a fazer manualmente uma tarefa repetitiva, estás a fazê-la mal!”

Então, comecei a pensar como poderia fazer esta configuração de forma mais sistemática para todas as camadas e campos, sem me causar tendinites. Depois de alguma pesquisa, cheguei às funções PyQGIS que apresento a seguir.

Tornar um campo apenas  de leitura

O campo identificador é gerado automaticamente pela base de dados, pelo que o utilizador não só não precisa de o editar, como não deve. Por essa razão, convém tornar o campo não editável.

Layer Properties - cabo_electrico | Attributes Form_103

Para o fazer programaticamente recorri ao seguinte código.

def field_readonly(layer, fieldname, option = True):
    fields = layer.fields()
    field_idx = fields.indexOf(fieldname)
    if field_idx >= 0:
        form_config = layer.editFormConfig()
        form_config.setReadOnly(field_idx, option)
        layer.setEditFormConfig(form_config)

# Exemplo para o campo "identificador"

project = QgsProject.instance()
layers = project.mapLayers() 

for layer in layers.values():
    field_readonly(layer,'identificador')

Configurar um campo com o widget DateTime

Os campos de datas ficam configurados automaticamente, mas o widget usado por omissão, ao contrário do que é exigido pela norma, apenas guarda a data e não a data e  hora.

Comecei por configurar como queria um campo de exemplo e depois fui ver como a configuração era gravada em PyQGIS usando a consola python:

>>>layer = iface.mapCanvas().currentLayer()
>>>layer.fields().indexOf('inicio_objeto')
1
>>>field = layer.fields()[1]
>>>field.editorWidgetSetup().type()
'DateTime'
>>>field.editorWidgetSetup().config()
{'allow_null': True, 'calendar_popup': True, 'display_format': 'yyyy-MM-dd HH:mm:ss', 'field_format': 'yyyy-MM-dd HH:mm:ss', 'field_iso_format': False}

Com isso consegui criar uma função que me permitisse configurar qualquer campo com a mesma configuração:

def field_to_datetime(layer, fieldname):
    config = {'allow_null': True,
              'calendar_popup': True,
              'display_format': 'yyyy-MM-dd HH:mm:ss',
              'field_format': 'yyyy-MM-dd HH:mm:ss',
              'field_iso_format': False}
    type = 'Datetime'
    fields = layer.fields()
    field_idx = fields.indexOf(fieldname)
    if field_idx >= 0:
        widget_setup = QgsEditorWidgetSetup(type,config)
        layer.setEditorWidgetSetup(field_idx, widget_setup)

# Exemplo para os campos "inicio_objeto" e "fim_objeto"

for layer in layers.values():
    field_to_datetime(layer,'inicio_objeto')
    field_to_datetime(layer,'fim_objeto')

Configurar um campo com o widget Value Relation

No modelo de dados, muitas tabelas contém campos que apenas aceitam um conjunto finito de valores. Valores estes que são listados noutra tabela, os chamados Foreign keys.

Para estes casos, é conveniente no QGIS configurar um widget de relação de tabela. Para o fazer de forma programática, o processo é identico ao mostrado anteriormente, em que há que descobrir primeiro o tipo e a configuração de uma campo já preparado. Mas neste caso, cada campo terá uma configuração ligeiramente diferente.

Felizmente, quem desenhou a estrutura de dados facilitou-nos a vida ao dar o mesmo nome aos campos e às tabela de valores associada, e todos eles começados com a texto “valor_”, tornando possivel que também essa parte seja automática.

A funçao abaixo começa por identificar para determinada camada todos os campos cujo nome começa por “valor_”. Depois iterando sobre os campos encontrados, adapta a configuração de forma a usar como camada de referência (‘Layer’) a camada com o mesmo nome que o campo.

def field_to_value_relation(layer):
    fields = layer.fields()
    pattern = re.compile(r'^valor_')
    fields_valor = [field for field in fields if pattern.match(field.name())]
    if len(fields_valor) > 0:
        config = {'AllowMulti': False,
                  'AllowNull': True,
                  'FilterExpression': '',
                  'Key': 'identificador',
                  'Layer': '',
                  'NofColumns': 1,
                  'OrderByValue': False,
                  'UseCompleter': False,
                   'Value': 'descricao'}
        for field in fields_valor:
            field_idx = fields.indexOf(field.name())
            if field_idx >= 0:
                print(field)
                try:
                    target_layer = QgsProject.instance().mapLayersByName(field.name())[0]
                    config['Layer'] = target_layer.id()
                    widget_setup = QgsEditorWidgetSetup('ValueRelation',config)
                    layer.setEditorWidgetSetup(field_idx, widget_setup)
                except:
                    pass
            else:
                return False
    else:
        return False
    return True
    
# Correr função em todas as camadas
for layer in layers.values():
    field_to_value_relation(layer)

Conclusão

Assim, de forma relativamente rápida, consegui configurar todas as camadas do projecto com os widgets que queria.

Peek 2019-09-30 16-06

Esta é a ponta do iceberg. Havendo necessidade, com um pouco de paciência e pesquisa, outras configurações podem ser alteradas usando PyQGIS. Por isso, pense nisso antes de começar a configurar camada a camada, campo a campo.

Advertisement

Saudades do QGIS (enquanto uso ArcGIS)

(aka Funcionalidades que os utilizadores de ArcGIS Desktop nem sonham que existem)

EN | PT

De tempos a tempos, leio artigos de comparação entre o ArcGIS e o QGIS. Uma vez que partem geralmente do ponto de vista de utilizadores de ArcGIS, acabam invariavelmente em observações parciais sobre a falta de funcionalidades do QGIS. Está na hora de mudar o ponto de vista. Por isso, convido-vos a acompanharem-me neste artigo (um pouco) longo, totalmente e assumidamente parcial.

“Olá, o meu nome é Alexandre, e tenho usado… QGIS

Eis algo que eu diria numa sessão de terapia em grupo dos Utilizadores Anónimos do QGIS. Estou a precisar de ir a uma sessão dessas porque, tendo sido recentemente forçado a voltar a usar – de forma temporária – o ArcGIS, sinto muita muita muita falta do QGIS em vários aspectos.

Em tempos idos, houve alturas em que usava o ArcGIS diariamente. Usei-o até à versão 9.3.1, até que me decidi a mudar para o QGIS (versão 1.7.4, acho eu). Na altura, senti falta de algumas (muitas?) funcionalidades do ArcGIS, mas estava disposto a trocá-las pela liberdade oferecida pela filosofia Open Source. Desde essa altura, passou-se muita coisa no universo QGIS, e eu tenho-me mantido avidamente atento à sua evolução. Esperaria que o mesmo tivesse acontecido no lado do ArcGIS Desktop, mas, ao que me parece, isso não aconteceu.

Estou a utilizar o topo de gama da ESRI, o ArcGIS 10.3, licença advanced, e debato-me para conseguir fazer pequenas coisas que são simplesmente inexistentes em ArcGIS.  Assim, o que se segue é uma lista de funcionalidades do QGIS das quais sinto falta.

Aviso: Para aqueles que usam exclusivamente o ArcGIS, algumas destas funcionalidades podem apanhá-los de surpresa.

Controlo de transparência

“O ArcGIS tem transparência! Está no separador Display, nas propriedades da camada!”

Sim, é verdade, mas… apenas é possível configurar transparência ao nível da camada. Ou seja, ou é tudo transparente, ou não é nada…

No QGIS, é possível determinar a transparência ao nível da camada, ao nível do  elemento/símbolo, e ao nível da cor. Podem achar que estou a sobrevalorizar o assunto, mas vejam a diferença nas imagens abaixo.

Transparencia_camadaTransparencia_elementoTransparencia_cor

Reparem que no QGIS é possível controlar a transparência sempre (ou quase sempre) que se define uma cor. Isto inclui em anotações (como as usadas nas imagens acima), em etiquetas, e em itens do compositor de impressão. É até possível determinar a transparência de uma cor usando a função RGBA() numa expressão! Que mais se pode pedir? 🙂

Screenshot from 2016-01-27 14:12:34

Modos de Blending

Esta funcionalidade é uma das preciosidades do QGIS, a possibilidade de combinar camadas como faríamos na maioria dos software de edição de imagem. Ao nível da camada e/ou elemento, é possível controlar como o mesmo irá interagir com os elementos e camadas abaixo. Para além do modo normal, estão disponíveis mais 12 modos: Lighen, Screen, Dodge, Darken, Multiply, Burn, Overlay, Soft light, Hard light, Difference and Subtract. Não me vou alongar sobre as propriedade de cada um. Vejam esta página para se informarem acerca da matemática por detrás de cada um deles e alguns exemplos.

Sem se experimentar um pouco, não é fácil perceber em que é que esta funcionalidade nos pode ser útil à produção cartográfica. Eu tive a oportunidade de o fazer enquanto tentava responder a esta pergunta.

2wph4

Uma das mais comuns utilizações para o blending é quando queremos realçar ou simular o relevo adicionando um hillshade por cima das restantes camadas. Em ArcGIS, apenas é possível controlar a transparência da camada, e o resultado final fica sempre um pouco esbatido em relação ao original. Mas no QGIS, é possível manter a força das cores originais usando o modo multiply na camada do hillshade.

Screenshot from 2016-01-27 15:24:38
Hipsometria com as cores originais
Screenshot from 2016-01-27 15:25:45
Cores da hipsometria esbatidas pelo hillshade transparente
Screenshot from 2016-01-27 15:24:45
Cores originais da hipsometria com o hillshade usando o multiply do QGIS

É também possível usar os modos de blending em elementos do compositor de mapas, permitindo combiná-los com outros elementos e texturas. Isto dá-nos a oportunidade de obter resultados mais “artísticos” sem a necessidade de pós-processamento num software de edição de imagem.

Configuração de cores

O eficiente controlo das cores é algo essencial para um cartógrafo, e o QGIS permite-nos controlá-las como profissionais que somos. É possível escolher as cores usando diferentes menus. Menus que poderá reconhecer de software como o Inkscape, Photoshop, Gimp, etc…

O meu favorito é o color picker. Ora vejam, usando o color picker, é possível recolhermos cores de qualquer sítio do nosso ecrã, fora ou dentro do QGIS. Algo muito útil e produtivo quando queremos usar uma cor já existente no nosso mapa, da legenda, de uma palete do  COLOURlovers ou do logo de uma empresa.

anim
Recollhendo uma cor fora do QGIS

Também podemos fazer copy/paste de cores entre menus, gravar e importar paletes de cores e até dar nome a uma cor e usá-la numa variável. Com tudo isto disponível, é-me difícil engolir o menu de selecção de cores do Windows. 😦

 

Modos “avançados” de simbologia de vectores

No ArcGIS, existem várias maneiras de simbolizar as camadas de vectores. Temos Single symbol, Unique values, Unique values many fields… e por aí fora. À primeira impressão, pode até parecer que ao QGIS faltam alguns destes modos, mas acreditem em mim, não faltam! Na verdade, o QGIS oferece muito mais flexibilidade no que toca a simbolizar as suas camadas.

Para começar, pode-se usar tanto ‘campos’ como ‘expressões’ em qualquer um dos modos de simbologia, enquanto que no ArcGIS apenas é possível usar ‘campos’. Alimentado por centenas de funções e com a possibilidade de criarmos as nossas próprias funções usando Python, o que é possível conseguir-se com expressões não tem limites. Torna-se possível seleccionar, recalcular, normalizar (etc…) um número infinito de campos para criar os nossos próprios “valores” (sem falar de que é possível aprimorar as etiquetas associadas aos valores para criar a legenda ideal).

Screenshot from 2016-01-20 22:34:54
Símbolos graduados no QGIS usando uma expressão para calcular a densidade populacional

E depois, no QGIS existem alguns modos “especiais” (e de certa forma bastante específicos) de simbologia, que nos fazem exclamar “wooooh”. Como, por exemplo, os polígonos invertidos, que permitem preencher o exterior dos polígonos (bom para mascarar outros elementos, os pontos desfasados, para mostrar pontos fisicamente demasiado próximos para serem representados, e o Heatmap que transforma qualquer camada de pontos num heatmap sem necessidade de conversão para raster e que é automaticamente actualizado sempre que editamos a camada de pontos.

Screenshot from 2016-01-20 22:58:44
Polígonos invertidos a mascarar o exterior de uma área de interesse

Mas deixei o melhor para o fim. O “One Renderer to rule them all“, a simbologia baseada em regras. Com este modo, é possível adicionar várias regras, agrupá-las numa estrutura de árvore, e atribuir-lhes um símbolo distinto. Cada elemento irá ser representado consoante cumpre ou não cada uma das regras. Isto dá aos utilizadores de QGIS controlo absoluto sobre a simbologia das suas camadas e que, em conjunto com o editor de expressões e as data-defined properties, abre a porta às mais diversas aplicações (veja alguns exemplos na secção abaixo).

rulesymbol_ng_line
Simbologia por regras

Atlas

Uma das minhas funcionalidade favoritas do QGIS é o Atlas do compositor de impressão. Eu sei que o ArcGIS tem o seu próprio “Atlas”, as Data Driven Pages, mas sinceramente, não é a mesma coisa.

Penso que conhecem o funcionamento básico destas ferramentas em ambos os softwares. Cria-se um layout de um mapa, escolhe-se uma camada de vectores como coverage e software irá criar um mapa, devidamente centrado e/ou aproximado para cada elemento da camada. É também possível adicionar etiquetas que irão mudar de acordo com os valores guardados nos atributos da camada.

Mas no QGIS as funcionalidades vão um pouco mais além…

Basicamente, podemos usar os atributos e geometria dos elementos da camada onde quer que seja possível usar uma expressão e, no QGIS, as expressões estão por todo o lado. Desta forma, a maioria das propriedades tanto de camadas, como dos elementos do mapa podem ser controlados pela camada usada no atlas.

Com a devida configuração, iterando por todos os elementos da camada de atlas, é possível escolher os elementos de outras camadas a mostrar ou a esconder, alterar a cor de base do seu mapa, rodar e redimensionar as páginas de acordo com as dimensões do elemento, escolher um logo específico para acompanhar cada mapa, e por aí fora. Mais uma vez, o céu é o limite.

mosaico_regioes_fixed
Série de mapas cuja dimensão foi automaticamente alterada para cobrir os elementos a uma escala fixa

Por isso, se se aliar a funcionalidade de Atlas com as data-defined properties, a simbologia por regras e as expressões, não me parece que o Data Driven Pages do ArcGIS seja um rival à altura. Discordam? Então tentem responder a esta questão.

Dica: Se realmente quiserem levar a produção de cartografia a outro nível de automatismo, usando bases de dados como Spatialite ou Postgis, é possível criar camadas de coverage adequadas para as vossas necessidades através de views. Acaba-se a redundância e a camada estará sempre actualizada.

Menus de estilo e etiquetas

Este é um caso mais de experiência do utilizador (UX) do que propriamente uma funcionalidade em falta, mas não imaginam como é confortável ter todas as opções das etiquetas e dos estilos em apenas um par de janelas (com vários separadores, claro).

Quando uso as opções de simbologia do ArcGIS parece que estou no filme “A origem (Inception)“, às tantas, já nem sei onde estou! Por exemplo, para adicionar um rebordo tracejado a um símbolo de uma camda de polígonos, é preciso abrir 5 janelas diferentes, e depois voltar para trás a clicar OK, OK, OK…

Capture
Opções de símbolos do ArcGIS

No QGIS, uma vez aberta a janela de propriedades da camada, todas as opções estão a um clique de distância (ou quase). E basta carregar em OK ou Aplicar uma vez para visualizar o resultado!

Screenshot from 2016-01-20 21:51:33
Opções de estilos do QGIS

Como bónus, é possível fazer copy/paste de uma camada para a outra, tornando a configuração do estilo de várias camadas muito mais rápida. Ao que me respondem:

“Não sejas ridículo! O ArcGIS também permite importar símbolos de outras camadas.”

Símbolos? Sim. Etiquetas? Não! E se, como eu, perdem algum tempo a configurar de forma primorosa as etiquetas de uma camada, ter de fazer o mesmo ou semelhante para outras camadas, vai-vos dar vontade de chorar… A mim dá.

(Vou deixar a comparação de múltiplos estilos por camada do QGIS vs Data Frames do ArcGIS para outra altura)

WFS

“O quê?!!”

Yup, é isso mesmo, o ArcGIS não suporta o standard OGC WFS a não ser que se compre uma extensão extra: A Extensão de Data Interoperability.

Com o universo SIG (e não só) a evoluir cada vez mais para Dados Abertos, Normas Abertas e Serviços Web OGC, esta situação revela uma posição extremamente mercantil por parte da ESRI. Se fosse um cliente ESRI, sentir-me-ia aldrabado. <sarcasmo> Ou talvez não… talvez me sentisse grato por mais uma oportunidade de investir algum dinheiro nas suas funcionalidades avançadas…<\sarcasmo>

No QGIS, como tudo o resto, o uso do WFS é livre. Tudo o que é preciso é adicionar um URL para o servidor WFS, e podemos começar a adicionar as camadas disponibilizadas, com a certeza de que estarão devidamente actualizadas pela entidade responsável pelo serviço.

Screenshot from 2016-01-20 21:58:54

Felizmente, para os utilizadores ArcGIS menos afortunados, existe sempre a “cómoda” possibilidade de fazerem o download das camadas através do browser de internet :-P.

http://giswebservices.massgis.state.ma.us/geoserver/wfs?request=GetFeature&service=wfs&version=1.0.0&typename=massgis:GISDATA.TOWNS_POLY&outputformat=SHAPE-ZIP

Ou então podem sempre usar o QGIS (ou outro open soure qualquer) para fazer o download. Mas não se esqueçam que as camadas não se irão actualizar sozinhas.

Editor de expressões

Já fiz menção às expressões várias vezes, mas para aqueles que desconhecem o editor de expressões, decidi terminar este artigo com umas das minhas funcionalidades favoritas.

Não conheço o suficiente do editor de expressões do ArcGIS para o poder criticar. Tanto quando percebo, podemos usá-lo para criar labels e para preencher um campo usando o field calculator. Sei que existem certamente muitas funções que podemos usar (apenas utilizei algumas) mas não são visíveis ao utilizador comum. Provavelmente é preciso consultar a documentação de ajuda para conhecê-las todas. É ainda possível criar funções em VBScript, Python e JsScript.

Capture

No QGIS, como já referi, podem-se usar expressões praticamente em todo o lado, o que é bastante conveniente para muitas aplicações. No que toca a funções, existem centenas disponíveis directamente na janela do editor de expressões, todas devidamente acompanhadas por informação sobre a sua sintaxe e alguns exemplos ilustrativos. Também se podem usar campos e valores como no ArcGIS, e até existe uma secção de “expressões recentes” para quando precisamos de reutilizar uma expressão.

Capture

Para além disso, também é possível criar as nossas próprias funções em Python (nada de VBScript ou JsScript), mas desta feita num editor próprio, num outro separador. Um editor equipado com autocomplete e code highlight para nos facilitar a vida, e que permite gravar as funções no ambiente do utilizador para serem usadas posteriormente (inclusive noutras sessões de QGIS).

Capture

Conclusão

Estas não são certamente as únicas funcionalidades do QGIS de que sinto falta, e não serão certamente as mais limitantes (por exemplo, não poder usar em pleno bases de dados Spatialite e Postgis vai, de certeza, tornar-me a vida num inferno nos próximos tempos), mas são aquelas que identifiquei assim que (re)abri o ArcGIS pelas primeiras vezes.

Para além disso, sinto que, com a  actual dinâmica de desenvolvimento do QGIS, a cada nova versão, esta lista irá crescer muito rapidamente. Embora ainda não tenha experimentado o ArcGIS Pro, na minha opinião, não me parece que a ESRI consiga acompanhar o ritmo.

“Ainda há coisas que sente falta do ArcGIS?” Claro que sim. Por exemplo, sinto falta de suporte para CMYK durante a exportação de mapas, mas não tanto como sinto falta do QGIS neste momento. Para além disso, sei que essas lacunas serão resolvidas mais cedo ou mais tarde.

No fundo, até gostei da oportunidade de voltar ao ArcGIS, pois permitiu-me reforçar a minha opinião acerca do QGIS. Tem tudo a ver com liberdade! Não só a liberdade de usar o programa quando e para o que bem entender (algo que para mim já era ponto assente), mas também a liberdade de controlar o programa em si e os seus outputs. Mantendo a facilidade de utilização para recém chegados e principiantes, muito foi feito para facilitar a vida de utilizadores experientes, e eles ficam eternamente agradecidos por isso (pelo menos eu fico).

Dito isto, The winner is… QGIS!!

O Fim

(de um artigo extremamente parcial)

Top Novas Funcionalidades do QGIS em 2015

EN | PT

Com o lançamento da primeira versão com suporte de longa duração (2.8 LTR) e mais duas versões estáveis (2.10 e 2.12), 2015 foi um ano fantástico (e atarefado) para a comunidade QGIS, com inúmeras melhorias e novas funcionalidades a chegarem ao QGIS.

Em jeitos de balanço, pedi aos utilizadores que escolhessem as funcionalidades introduzidas em 2015 suas favoritas (da lista do registo visual de alterações). Como resultado, obtive o seguinte top 5 de novas funcionalidades.

5 – Melhorias na consola python (2.8)

Com a versão 2.8, passou a ser possível arrastar e largar scripts Python para a janela do QGIS, sendo os mesmos executados automaticamente. Existe também um novo ícone na barra de ferramentas dos módulos e um atalho (Ctrl-Alt-P) para acesso rápido à consola Python.

4 – Novos algoritmos de processamento (2.8)

Também no 2.8, foram introduzidos novos algoritmos à framework de processamento. Se trabalha em análise espacial, estas adições poderão muito bem ter-lhe feito ganhar o dia (ou o ano).

  • Algoritmo Pontos regulares
  • Algoritmo Diferença simétrica
  • Algoritmo Separação de vectores
  • Algoritmo Grelha de vectores
  • Algoritmo de cálculo de curvas hipsométricas
  • Algoritmo Separar linhas com linhas
  • Reconstrução do algoritmo de manipulação de campos

3 – Simbolizar por regras em árvore na legenda (2.8)

Ao longo de 2015 foram feitas algumas melhorias à legenda do QGIS. A versão 2.8 trouxe-nos a visualização da legenda de camadas simbolizadas por regras em formato de árvore. Melhor que isso, cada nó da estrutura de árvore pode ser ligada ou desligada, possibilitando uma excelente flexibilidade na escolha de sub-camadas a desenhar no mapa.

2 – Ferramentas avançadas de edição (2.8)

Alguma vez desejou, no QGIS, desenhar linhas paralelas ou com ângulos rectos,  trancar as linhas a determinados ângulos ou distâncias e por aí a fora? Então as suas preces foram ouvidas. As ferramentas avançadas de edição começaram como módulo CADinput e foram integradas no QGIS na versão 2.8, adicionando-lhe mais um painel. O painel fica activo quando se procede ao desenho de geometrias.

Untitled

1 – Etiquetas por regras (2.12)

Esta era uma funcionalidade há muito esperada (pelo menos por mim), e foi votada pela maioria dos utilizadores. A partir da versão 2.12, é possível definir estilos de etiquetas com base em regras. Isto permite um ainda maior controlo sobre o posicionamento e estilo das etiquetas. Tal como no caso das camadas simbolizadas por regras, as regras das etiquetas podem ser agrupadas para permitir a definição das opções de estilo de uma forma extremamente fléxivel. Por exemplo, é possível desenhar etiquetas diferentes consoante o tamanho dos respectivos elementos (tal como é exemplificado na imagem).

image25

Houve outras funcionalidades a fazerem as delícias de muitos utilizadores. Por exemplo, as Melhorias/consistência na selecção de projecções (2.8), Melhorias no provider PostGIS (2.12), Módulo para validar geometrias e alinhar geometrias (2.12), Múltiplos estilos por camada (2.8).

Discorda desta lista? Então ainda vai a tempo de fazer valer o seu voto. Também pode consultar aqui os resultados na integra.

Obviamente, esta lista vale o que vale. Tratou-se de um mero exercício. Até porque, com a tamanha diversidade de utilizadores QGIS, seria impossível criar uma lista que nos agradasse a todos. Para além disso, houve muitos aperfeiçoamento, feitos em 2015, que poderão ter passado despercebidos à maioria dos utilizadores. Consulte o registo visual de alterações para ver a lista completa de funcionalidades e melhorias.

Em meu nome, a todos os programadores, patrocinadores e colaboradores do QGIS,

MUITO OBRIGADO PELO VOSSO FANTÁSTICO TRABALHO!I

desejo-vos um óptimo (e produtivo) 2016.

Dica para ajustar posição de símbolos em QGIS

EN | PT

De quando em vez aparecem-me zonas com demasiado símbolos no mesmo local, e pensei como seria fantástico se os pudesse arrastar para um local mais conveniente sem ter de alterar as suas geometrias, tal como é possível fazer com as etiquetas. Esse pensamento deu-me a ideia base para a dica que vou demonstrar.

Escolha a sua camada de pontos e comece por criar dois novos campos chamados symbX e symbY (Tipo: Decimal; Tamanho: 20; precisão: 5). No separador “Estilo” das propriedades da camada, defina para cada nível do seu símbolo o seguinte: Escolher “unidade do mapa” como a unidade para as opções de afastamento; Usar a seguinte expressão na opção afastamento das propriedades definidas por dados.


CASE WHEN symbX IS NOT NULL AND symbY IS NOT NULL THEN
    tostring($x - symbX) + ',' + tostring($y - symbY)
ELSE
    '0,0'
END

Screenshot from 2015-02-22 18:18:43

Tenha atenção que, se as coordenadas do seu mapa tiver valores negativos, será necessário uma pequena alteração ao código. E. g., se tiver valores negativos em X deverá usar-se  antes a expressão “tostring(symbX -$x)”.

De forma temporária coloque etiquetas na sua camada usando um texto pequeno (eu usei o ‘+’ (sinal de mais) centrado e com um buffer branco) e defina as coordenadas X e Y dos propriedades definidadas por dados usando os campos symbX e symbY,

Screenshot from 2015-02-22 22:42:07

A partir desse momento, quando usar a ferramenta de mover etiquetas, não só alterará a posição da etiqueta, mas também a do próprio símbolo! Fantástico, não?

anim

Note que as geometria dos elementos não são alteradas durante o processo. Para além disso, lembre-se que neste caso também poderá adicionar linhas de guia para ligar os símbolos à posição original do ponto.

Séries de mapas com formatos múltiplos em QGIS 2.6 – Parte 1

EN | PT

Para não variar, a nova versão do QGIS (o QGIS 2.6 Brigthon) traz um conjunto alargado de novas funcionalidades que permitem ao utilizador fazer mais, melhor e mais rápido do que com a versão anterior. Uma das novidades desta versão é a possibilidade de controlar algumas propriedades dos itens do compositor através de dados (por exemplo, o tamanho e a posição). Algo que abre a porta a aplicações bastante interessantes. Nos próximos artigos, proponho-me a mostrar como criar séries de mapas com multiplos formatos.

Neste primeiro artigo, o objectivo é que, mantendo o tamanho da folha, o mapa seja criado com a orientação (paisagem ou retrato) que melhor se adapte à forma do elemento do atlas. Para exemplificar, usei a amostra de dados do Alaska para criar  um mapa de cada uma das regiões do Alaska.

Em primeiro lugar comecei por criar o meu layout numa dos formatos, colocando vários itens nas posições que desejava.

mapa_base_atlas

Para  controlar a orientação da folha através do atlas, fui ao separador “Composição” e na opção orientação, usei no botão propriedades definidos por dados a seguinte expressão:

CASE WHEN bounds_width( $atlasgeometry ) >=  bounds_height( $atlasgeometry ) THEN 'landscape' ELSE 'portrait' END

Usando a opção de pré-visualização do atlas, podemos verificar que a orientação da folha já muda de acordo com a forma do elemento do atlas. No entanto, os itens não acompanham essa mudança e alguns ficam até fora da área de impressão.

Screenshot from 2014-11-08 23:29:49

Para controlar o tamanho e posição dos itens do mapa tive em consideração o tamanho de uma folha A4 (297 x 210 mm), as dimensões das margens do mapa ( 20 mm, 5 mm, 10 mm, 5 mm) e os pontos de referência dos itens.

No caso do item “mapa”, usando como ponto de referência o canto superior esquerdo, foi necessário alterar a sua altura e largura. Sabia que a altura do item era é subtracção do tamanho das margens superiores e inferiores (30 mm) da altura folha por isso a expressão a usar foi:

(CASE WHEN  bounds_width(  $atlasgeometry ) >=  bounds_height( $atlasgeometry) THEN 297 ELSE 210 END) - 30

De forma análoga, a expressão a usar para a largura foi:

(CASE WHEN  bounds_width(  $atlasgeometry ) >=  bounds_height( $atlasgeometry) THEN 210 ELSE 297 END) - 10

Screenshot from 2014-11-09 00:02:15

Os restantes itens ocupavam sempre uma posição relativa na folha sem que fosse necessário alterar o seu tamanho e por isso tinha apenas de controlar a sua posição. Por exemplo, o título encontrava-se centrado no topo da folha, e portanto, usando como ponto de referência o topo-centro, bastou definir a seguinte expressão para a posição X:

Screenshot from 2014-11-09 00:13:17

(CASE WHEN  bounds_width(  $atlasgeometry ) >=  bounds_height( $atlasgeometry)  THEN 297 ELSE 210 END)  / 2.0

Screenshot from 2014-11-09 00:30:57

Já a legenda exige alterar a posição em X e em Y. Usando como ponto de referência o canto inferior direito, a expressão para a posição em X foi:

(CASE WHEN  bounds_width(  $atlasgeometry ) >=  bounds_height( $atlasgeometry) THEN 297 ELSE 210 END) - 7

E para a posição em Y:

(CASE WHEN  bounds_width(  $atlasgeometry ) >=  bounds_height( $atlasgeometry) THEN 210 ELSE 297 END) - 12

Screenshot from 2014-11-09 00:47:28

Para os restantes itens (rosa dos ventos, escala gráfica e texto no canto inferior esquerdo), as expressões a usar eram em tudo similares às já apresentadas, e, após definidas em cada um dos itens, fiquei com o layout preparado para se adaptar às duas orientações da folha.

output_9

Depois disso, a impressão/exportação de todos os (25) mapas ficou à distância de um só clique.

mosaico_regioes

No próximo artigo da série, procurarei explicar como criar séries de mapas em que seja o tamanho da folha a adaptar-se de forma a manter uma escala constante.

Instalar duas versões de QGIS em Linux

Instalar duas versões de QGIS em Linux

QGIS24_QGISmaster

Em altura de testes à versão em desenvolvimento do QGIS (versão master), dá jeito  ter também instalada a última versão estável do QGIS. Em windows isso não representa um problema, uma vez que se podem instalar várias versões do QGIS em paralelo (tanto via Osgeo4w como standalone). Em linux, o processo não é tão directo pelo facto da instalação se realizar por obtenção de diversos pacotes disponíveis nos repositórios, não sendo por isso possível instalar mais do que uma versão sem que se originem quebras de dependências. Assim, instalando a versão estável através dos repositórios, as alternativas para instalação da versão em desenvolvimento são:

  • Compilar o QGIS master do código fonte;
  • Instalar o QGIS master num docker;
  • Instalar o QGIS master numa máquina virtual;

Neste artigo vou mostrar como compilar o código fonte em Ubuntu 14.04. Afinal não é tão difícil quanto parece. Meia dúzia de comandos e um pouco de paciência e vai-se lá. Usei como base as indicações do ficheiro INSTALL.TXT disponível no código fonte com umas pequenas alterações.

Instalar todas as dependências necessárias

Num terminal correr o seguinte comando para instalar todas as dependências e ferramentas necessárias à compilação do QGIS. (adicionei o ccmake e o git ao comando original)

sudo apt-get install bison cmake doxygen flex git graphviz grass-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl0-dev libopenscenegraph-dev libosgearth-dev libpq-dev libproj-dev libqscintilla2-dev libqt4-dev libqt4-opengl-dev libqtwebkit-dev libqwt5-qt4-dev libspatialindex-dev libspatialite-dev libsqlite3-dev lighttpd pkg-config poppler-utils pyqt4-dev-tools python-all python-all-dev python-qt4 python-qt4-dev python-sip python-sip-dev spawn-fcgi txt2tags xauth xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xvfb cmake-curses-gui

Configurar o ccache

Este passo permite optimizar a compilação e tornar a compilação mais rápida nas próximas vezes que se fizer:

cd /usr/local/bin
sudo ln -s /usr/bin/ccache gcc
sudo ln -s /usr/bin/ccache g++

 Obter o código fonte do Github

O código fonte pode ser colocado numa pasta à escolha de cada um. Seguindo a sugestão do ficheiro de instruções acabei por colocar tudo na minha pasta home/alexandre/dev/cpp.

mkdir -p ${HOME}/dev/cpp
cd ${HOME}/dev/cpp

Já dentro da pasta home/alexandre/dev/cpp, podemos obter o código do qgis executando o seguinte comando git:

git clone git://github.com/qgis/QGIS.git

Nota: Se pretendesse fazer alterações ao código e experimentar se funcionava, então deveria fazer o clone do fork do qgis do meu próprio repositório, ou seja:

git clone https://github.com/SrNetoChan/Quantum-GIS

Preparar directorias de compilação e instalação

O código fonte tem de ser compilado e instalado em locais próprios para evitar conflitos com outras versões do QGIS. Por isso, há que criar uma pasta para efectuar a instalação:

mkdir -p ${HOME}/apps

E outra onde será feita a compilação:

cd QGIS
mkdir build-master
cd build-master

Configuração

Já na pasta build-master damos início ao processo de compilação. O primeiro passo é a configuração, onde vamos dizer onde queremos instalar o QGIS master. Para isso executamos o seguinte comando (não esquecer os dois pontos):

ccmake ..

Na configuração é necessário alterar o valor do CMAKE_INSTALL_PREFIX que define onde vai ser feita a instalação, no meu caso usei a pasta já criada ‘home/alexandre/apps’ . Para editar o valor há que mover o cursor até à linha em causa e carregar em [enter], depois de editar, volta-se a carregar em [enter]. Depois há que carregar em [c] para refazer a configuração e depois em ‘g’ para gerar a configuração.

Screenshot from 2014-10-08 23:33:39

 Compilação e instalação

Já com tudo configurado resta compilar o código e depois instalá-lo:

make
sudo make install

Nota: Estes dois passos podem demorar um bocadinho, principalmente na primeira vez que o código for compilado.

Depois de instalado podemos correr o QGIS master a partir da pasta de instalação:

cd ${HOME}/apps/bin/
export LD_LIBRARY_PATH=/home/alexandre/apps/lib
export QGIS_PREFIX_PATH=/home/alexandre/apps
${HOME}/apps/bin/qgis

Para se tornar mais cómodo, podemos colocar os últimos 3 comandos num ficheiro .sh e gravá-lo num local acessível (desktop ou home) para executarmos o qgis sempre que necessário.

Screenshot from 2014-10-09 00:36:52

UPDATE: Actualizar a versão master

Como já foi referido num comentário, a versão em desenvolvimento está constantemente a ser alterada, por isso para testar se determinados bugs foram entretanto corrigidos há que a actualizar. Trata-se de um processo bastante simples. O primeiro passo é actualizar o código fonte:

cd ${HOME}/dev/cpp/qgis
git pull origin master

E depois é voltar a correr a compilação (que desta feita será mais rápida):

cd build-master
ccmake ..
make
sudo make install

Coordenadas dos cantos do mapa em QGIS

Coordenadas dos cantos do mapa em QGIS

EN | PT

O desafio

Em tempos na lista de discussão do qgis-pt alguém perguntou como dispor as coordenadas dos cantos do mapa no QGIS. Não estando (ainda) disponível tal funcionalidade, tentei chegar sem sucesso a uma solução que fosse de certa forma automática. Depois de remoer a ideia, e de ler um artigo do Nathan Woodrow, achei que a solução poderia passar por criar uma função para o construtor de expressões que pudesse ser usada em etiquetas no mapa.

 A solução

Seguindo as indicações do referido artigo, comecei por criar um ficheiro userfunctions.py, que gravei na pasta .qgis2/python e, com uma ajuda do Nyall Dawson, escrevi o seguinte código.

from qgis.utils import qgsfunction, iface
from qgis.core import QGis

@qgsfunction(2,"python")
def map_x_min(values, feature, parent):
 """
 Returns the minimum x coordinate of a map from
 a specific composer.
 """
 composer_title = values[0]
 map_id = values[1]
 composers = iface.activeComposers()
 for composer_view in composers():
  composer_window = composer_view.composerWindow()
  window_title = composer_window.windowTitle()
  if window_title == composer_title:
   composition = composer_view.composition()
   map = composition.getComposerMapById(map_id)
   if map:
    extent = map.currentMapExtent()
    break
 result = extent.xMinimum()
 return result

Depois de correr o comando import userfunctions na consola python (Módulos > Consola python), já conseguia usar a função map_x_min() (disponível na categoria python) numa expressão para obter o valor mínimo em X.

Screenshot from 2014-09-09 16^%29^%29
Bastava então criar as restantes funções map_x_max(), map_y_min() e map_y_max(). Como parte do código seria repetida, decidi encapsulá-lo na função map_bound() que recebesse como argumentos o título do compositor de impressão e o id do mapa e me devolvesse a extensão do mesmo (sob a forma de um QgsRectangle).

from qgis.utils import qgsfunction, iface
from qgis.core import QGis

def map_bounds(composer_title, map_id):
 """
 Returns a rectangle with the bounds of a map
 from a specific composer
 """
 composers = iface.activeComposers()
 for composer_view in composers:
  composer_window = composer_view.composerWindow()
  window_title = composer_window.windowTitle()
  if window_title == composer_title:
   composition = composer_view.composition()
   map = composition.getComposerMapById(map_id)
   if map:
    extent = map.currentMapExtent()
    break
 else:
  extent = None

 return extent

Com essa função disponível podia usá-la internamente nas funções para devolver cada um dos mínimos e máximos em X e Y, tornando o código mais compacto e fácil de manter. Adicionei ainda ao código original alguns mecanismos para evitar erros.

@qgsfunction(2,"python")
def map_x_min(values, feature, parent):
 """
 Returns the minimum x coordinate of a map from a specific composer.
 Calculations are in the Spatial Reference System of the project.
<h2>Syntax</h2>
map_x_min(composer_title, map_id)
<h2>Arguments</h2>
composer_title - is string. The title of the composer where the map is.
 map_id - integer. The id of the map.
<h2>Example</h2>
map_x_min('my pretty map', 0) -> -12345.679

 """
 composer_title = values[0]
 map_id = values[1]
 map_extent = map_bounds(composer_title, map_id)
 if map_extent:
  result = map_extent.xMinimum()
 else:
  result = None

 return result

@qgsfunction(2,"python")
def map_x_max(values, feature, parent):
 """
 Returns the maximum x coordinate of a map from a specific composer.
 Calculations are in the Spatial Reference System of the project.
<h2>Syntax</h2>
map_x_max(composer_title, map_id)
<h2>Arguments</h2>
composer_title - is string. The title of the composer where the map is.
 map_id - integer. The id of the map.
<h2>Example</h2>
map_x_max('my pretty map', 0) -> 12345.679

 """
 composer_title = values[0]
 map_id = values[1]
 map_extent = map_bounds(composer_title, map_id)
 if map_extent:
  result = map_extent.xMaximum()
 else:
  result = None

 return result

@qgsfunction(2,"python")
def map_y_min(values, feature, parent):
 """
 Returns the minimum y coordinate of a map from a specific composer.
 Calculations are in the Spatial Reference System of the project.
<h2>Syntax</h2>
map_y_min(composer_title, map_id)
<h2>Arguments</h2>
composer_title - is string. The title of the composer where the map is.
 map_id - integer. The id of the map.
<h2>Example</h2>
map_y_min('my pretty map', 0) -> -12345.679

 """
 composer_title = values[0]
 map_id = values[1]
 map_extent = map_bounds(composer_title, map_id)
 if map_extent:
  result = map_extent.yMinimum()
 else:
  result = None

 return result

@qgsfunction(2,"python")
def map_y_max(values, feature, parent):
 """
 Returns the maximum y coordinate of a map from a specific composer.
 Calculations are in the Spatial Reference System of the project.
<h2>Syntax</h2>
map_y_max(composer_title, map_id)
<h2>Arguments</h2>
composer_title - is string. The title of the composer where the map is.
 map_id - integer. The id of the map.
<h2>Example</h2>
map_y_max('my pretty map', 0) -> 12345.679

 """
 composer_title = values[0]
 map_id = values[1]
 map_extent = map_bounds(composer_title, map_id)
 if map_extent:
  result = map_extent.yMaximum()
 else:
  result = None

 return result

As funções ficaram disponíveis no construtor de expressões na categoria “Python” (podia ter-lhe dado outro nome qualquer) e as descrições das funções são transformadas em textos de ajuda para fornecer ao utilizador informação de como utilizar as funções.

Screenshot from 2014-09-09 15^%39^%19

Usando as funções recentemente criadas, foi fácil posicionar etiquetas  junto dos cantos do mapa com as coordenadas dos mesmos. Qualquer alteração à extensão do mapa, reflecte-se nas etiquetas, podendo por isso ser usadas convenientemente com a funcionalidade de atlas.

Screenshot from 2014-09-09 15^%40^%27

O resultado destas funções pode ser usado com outras. Na imagem seguinte apresenta-se uma expressão para apresentar as coordenadas de forma mais compacta.

Screenshot from 2014-09-09 15^%43^%55

Havia um senão… Para as funções ficarem disponíveis, seria necessário importá-las manualmente em cada utilização do QGIS. Algo que não era prático. Novamente com a ajuda do Nathan, fiquei a saber que podemos importar módulos Python no arranque do QGIS colocando na pasta .qgis2/python um ficheiro com o nome startup.py com os comandos de importação. Para o meu caso bastou o seguinte.

import userfunctions

Conclusões

Fiquei bastante satisfeito com o resultado. A possibilidade do utilizador criar as usas próprias funções para usar em expressões vem mais uma vez demonstrar como é fácil personalizar e criar as minhas próprias ferramentas para QGIS. Já estou a matutar em mais aplicações para estar fantástica funcionalidade.

UT 9 - Qta da Peninha - Vegetação potencial

Os ficheiros Python com as funções criadas podem ser descarregados AQUI. Basta descompactar os dois ficheiros para a pasta .qgis2/python e reiniciar o QGIS, e as funções devem ficar disponíveis.

Por favor, use o operador “IN”

Por favor, use o operador “IN”

EN | PT

Já não é a primeira vez que vejo pessoas que para seleccionarem elementos pelos valores dos seus atributos, usam expressões como

"field" = 'value1' OR "field" = 'value2' OR "field" = 'value3' [OR ...]

Uma forma mais prática e bonita de o fazer é usar o operador IN.

"field" IN ('value1','value2','value3'[,...])

Este operador existe em quase todos os softwares SIG que conheço. No QGIS, pode ser usado mesmo quando não existe um botãozinho para clicar.

Captura de tela 2014-04-23 16.50.40

Na verdade, trata-se de uma abreviatura do que é usado em SQL, onde o operador é usado na expressão WHERE.

SELECT *
FROM parks
WHERE "tipo" IN ('PI','CM','PJ');

Old map in QGIS

Old map in QGIS

EN | PT

Inspirado num artigo da Anita Graser, tentei usar o QGIS para criar um mapa de Cascais que tivesse um aspecto antigo, como que se tivesse sido metodicamente desenhado à mão, embora tivesse ligeiramente maltratado.

Definir os Estilos

Comecei por definir a simbologia para cada um dos elementos a representar.

Edifícios

Para preenchimento dos edifícios tentei usar uma cor que lembrasse os telhados portugueses, e muito usada em mapas antigos de cidades, com um contorno ligeiramente mais escuro do mesma cor.

Para dar dimensão aos edifícios criei uma sombra por baixo, adicionando um “simple fill” em tons escuros e usando a opção Offset X,Y. Os valores escolhidos tiveram em conta a direcção predominante das fachadas dos edíficios de forma a que o efeito fosse visível por toda a área do mapa.

Capturar_4

Capturar_6

Espaços verdes

Para espaços verdes, usei 3 camadas de simbologia. Uma base com o preenchimento a verde. Uma segunda camada com um contorno grosso ligeiramente mais escuro, e com uma funcionalidade que surgiu na versão 2.2 e que permite mostrar as linhas de contorno apenas no interior do polígono. Para tal é necessário escolher o tipo “outline: simple line” e seleccionar a opção “draw line only inside polygon”.

Capturar_5

.A última camada de simbologia é uma linha fina num verde mais escuro que as restantes.

Capturar_7

O Mar

Para o mar usei a mesma técnica que para os espaços verdes, mas em tons de azul e com o contorno do meio mais exagerado.

Capturar_8

 Estradas

Para símbolo das estradas usei uma linha grossa com um tom pastel alaranjado. Criei também etiquetas dos nomes das ruas ao longo das linhas usando uma fonte script (no meu caso o Pristina Bold). Para melhorar a legibilidade adicionei um pequeno buffer branco com 50% de transparência.

Captura de tela 2014-04-11 17.55.04

Capturar_9

Praia

Nas praias, para além da base, usei um point pattern fill, com um círculo bastante pequeno.

Capturar_11Capturar_10

Composição do mapa

Embora o aspecto do mapa não esteja muito longe do resultado final, é no Print Composer que se dão os toques finais. Em primeiro lugar, comecei por preencher toda a folha com a imagem de uma textura de papel antigo (aliás, o mesmo usado pela Anita no seu artigo). Para o efeito não ficar demasiado pesado, apliquei uma transparência de 20% à imagem.

Captura de tela 2014-04-14 11.24.53

Depois adiciona-se o mapa propriamente dito e nas suas propriedades alteramos o modo de rendering de “normal” (usado por defeito) para “multiply“. Desta forma parece que o mapa foi desenhado directamente sobre o papel antigo.

Captura de tela 2014-04-14 11.30.07

Depois é uma questão de adicionar mais umas etiquetas (nomes de praias e locais), uma rosa dos ventos e uma escala gráfica (usando sempre o modo de rendering “multiply” para parecer que foi desenhado por cima da folha), e… Voilá, temos mapa!

mapa_antigo

Mapas de fluxos em QGIS

Mapas de fluxos em QGIS

Hoje surgiu a questão “Como consigo fazer um mapa em que a sobreposição de símbolos aumente a opacidade?“. Fiz o meu melhor para descrever como fazê-lo em QGIS, que transcrevo agora para português.

Este tipo de mapas pode ser feito em QGISs usando a uma combinação da transparência e cor dos símbolos e o blending mode dos elementos.

Note-se a diferença entre a transparência e blending mode da camada (que é aplicado a toda a camada) e a transparência do símbolo e blending dos elementos (que acumulam com outros elementos da mesma camada).

Esta opções estão disponíveis em Propriedades da camada > Estilo.

testes_opacidade_opcoes

Com um valor de transparência do símbolo de 95%, a cor do elemento tornar-se à totalmente opaca quando pelo menos 20 elementos de sobrepuserem. Este número é limitado à sobreposição de 100 elementos(tranparencia 99%).

Usando diferentes modos de blending (como a multiplicação ou a adição) consegues-se obter outros efeitos.

Testes_com_opacidade_2

Duplicando a camada, usando diferentes cores (no exemplo abaixo o verde para uma camada e o vermelho para a imediatamente baixo) e usando blending mode dogde,consegue-se obter efeitos ainda mais interessantes.

opacity dodge