Eliminação de sobreposições e lacunas entre polígonos numa camada (com QGis e Geopackage)

Aqui retomamos o exemplo abordado no artigo Eliminação de sobreposições e espaços entre polígonos numa camada (com QGis e Postgis) para ver o mesmo tipo de solução quando não se tem uma base de dados PostgreSQL/Postgis. Aqui só vamos utilizar as possibilidades oferecidas pelo QGis ao trabalhar com um formato de dados Geopackage.

Se tiver a oportunidade de trabalhar com os dados cadastrais franceses correspondentes aos Localidades, verificará que a consistência espacial (topologia) não é respeitada:

De facto, o limite de cada localidade é o limite da estrada adjacente, o que deixa espaços vazios onde se encontram as estradas. Embora em alguns casos isto não seja um problema, torna-se um problema quando se adiciona a camada “Comunas” (do mesmo cadastro) ao mapa:

A esta escala não parece muito limpo, mas se fizermos um zoom é ainda pior.

E se olharmos para a camada de localidade propriamente dita, encontramos numerosas anomalias topológicas:

Aqui vamos ver como resolver o primeiro problema: Como corrigir a topologia da camada de localidade, removendo polígonos sobrepostos e espaços vazios entre eles.

Para o segundo problema: Como recriar uma camada comum consistente com a nova camada de localidades e sobreposta exatamente aos limites das localidades, consulte o artigo citado acima (Eliminação de sobreposições e espaços entre polígonos numa camada (com QGis e Postgis), uma vez que esta parte utiliza simplesmente o QGis e o Geopackage.

O exemplo abaixo foi criado utilizando os dados do registo predial oficial do departamento 71, descarregado a partir do link https://cadastre.data.gouv.fr/data/etalab-cadastre/2023-01-01/shp/departements/71/

Como corrigir a topologia da camada de localidade

A solução aqui proposta não requer uma base de dados PostgreSQL/Postgis. No entanto, dadas as limitações do SQLite3 e um bug no DB Manager do QGis 3.30, haverá algumas manipulações adicionais. Deve também contar com tempos de processamento longos, razão pela qual não é adequado para o processamento de grandes camadas.

1-Criar uma camada com um buffer à volta das localidades

Para gerir os espaços entre polígonos, mesmo que certas ferramentas de encaixe possam ser utilizadas para lidar com certos problemas, a solução mais simples e mais radical é construir um buffer à volta dos polígonos de modo a transformar os espaços vazios em sobreposições. No caso das localidades, os espaços vazios são da ordem dos 10m. Construímos um buffer de 6m à volta das localidades, o que dará uma sobreposição de cerca de 2-3 metros.

Escolha um ficheiro de saída permanente no formato Geopackage, que lhe permitirá seguir o procedimento no passo seguinte diretamente sem modificações.

O resultado da camada tampão é o seguinte:

Já não temos de gerir os espaços entre os polígonos, apenas temos sobreposições.

2- Abrir o QGis DataBase Manager

Aparecerá a janela do DB Manager

Se o seu ficheiro geopackage não aparecer na lista de ficheiros, clique com o botão direito do rato em Geopackage->New connection e carregue-o.

Clique na camada armazenada em buffer na etapa anterior e, em seguida, no menu Database (Base de dados) -> SQL Window (Janela SQL).

3- Execute as linhas do guião SQL

Todas as linhas do script seguinte correspondem às seguintes tarefas

  1. Criar uma vista com duas colecções de geometrias. Inicialmente, estas são os polígonos das localidades em duplicado.
  2. A primeira coleção contém as partes dos polígonos que não se sobrepõem a outras
  3. As partes que se sobrepõem são mantidas na segunda coleção
  4. Por fim, adicionamos a parte sobreposta ao mais pequeno dos dois polígonos afectados pela sobreposição.

Ao contrário da janela SQL no pgAdmin e PostgreSQL/Postgis, na janela SQL do DB Manager é necessário executar o script consulta por consulta.

Para adaptar o script ao seu caso, é necessário substituir os seguintes elementos utilizando um processador de texto:

  1. todas as ocorrências de tampon pelo nome da sua tabela que contém os localidades em buffer,
  2. todas as ocorrências de table_corrigee pelo nome da tabela de resultados que pretende,
  3. e verifique se o identificador da sua tabela armazenada em buffer é id. Por defeito, pode ter o nome fid. Neste caso, substitua todas as ocorrências de id por fid.

Aqui estão as linhas do script:

Primeira consulta (se já tiver executado o script)

DROP TABLE IF EXISTS table_corrigee ; 

Segunda consulta (se já tiver executado o script)

DROP VIEW auto_jointure;

Terceira consulta

CREATE OR REPLACE VIEW auto_jointure AS SELECT

    tampon.id as id,
    tampon.nom as "nom",
    tampon.commune as "commune",
-- recupera todos os polígonos da tabela buffer em duas colecções: uma contendo as geometrias completas e outra contendo as partes sobrepostas. De momento, ambas as colecções contêm as geometrias completas
    ST_Union(tampon.geom) AS full_geom,
    ST_Union(tampon_bis.geom) AS shared_geom
    FROM  tampon ,tampon AS tampon_bis
    WHERE
      --verificar a validade do polígono como precaução
      ST_IsValid(tampon.geom) AND ST_IsValid(tampon_bis.geom)
      --filtro para reter os polígonos que se intersectam
      AND ST_intersects(tampon.geom,tampon_bis.geom)   
      --eliminar os polígonos que se auto-intersectam
      AND tampon.id <> tampon_bis.id          
      --para uma intersecção de 2 polígonos, manter apenas o mais pequeno
      AND ST_Area(tampon_bis.geom) < ST_Area(tampon.geom)
      --Como estamos a fazer "uniões", temos de efetuar um agrupamento nos outros atributos
    GROUP BY tampon.id,tampon."nom" , tampon.commune ;

Quarta consulta

/*
Vamos criar uma tabela que conterá o resultado final: o primeiro passo é remover todas as áreas sobrepostas. O segundo passo consiste em adicionar as áreas sobrepostas ao menor dos dois polígonos. Os buracos criados pelo primeiro passo são preenchidos por este segundo passo. Os polígonos finais estão unidos, sem sobreposições ou espaços vazios.
*/

    CREATE TABLE table_corrigee AS SELECT
    id,
    "nom",
    commune,
/* As intersecções são subtraídas da camada que contém todos os polígonos; as partes em conflito são assim eliminadas*/
    ST_Multi(ST_Difference(full_geom,shared_geom)) as geom,
    ST_Area(full_geom) as area
    FROM auto_jointure
    WHERE ST_IsValid(full_geom) AND ST_IsValid(shared_geom)
/*Devemos então adicionar as intersecções que acabámos de subtrair para preencher os espaços criados.*/
    UNION 
      SELECT
      id,
      "nom",
      commune,
      geom,
      ST_Area(geom)
      FROM tampon
      WHERE id NOT IN (SELECT id FROM auto_jointure);

Resolução de problemas do DB Manager

Depois de executar as consultas, poderá ficar surpreendido ao ver que nem as vistas estáveis nem as vistas criadas durante os scripts aparecem na lista de tabelas do Geopackage..

No entanto, se escrever uma consulta que faça referência às tabelas de script, elas funcionam. As tabelas estão algures, mas o DB Manager não as vê… É um erro, conhecido e reconhecido, e… aceite! Como os criadores do QGis estão a preparar um substituto para o DB Manager, o Data Source Manager, não têm intenção de resolver este problema.

Em suma, se não podemos resolver o problema, podemos contorná-lo.

Com o DB Manager, vamos criar uma tabela, com a opção padrão

E criamos uma tabela com os mesmos campos que a camada buffer

Aparece na lista de tabelas do geopackage

Agora, tudo o que temos de fazer é carregar o resultado do nosso script nesta tabela “oficial” utilizando a seguinte consulta SQL:

insert into recup
select fid,geom,nom,commune from lieux_dits_corr

Carregamos esta nova camada no QGis:

À esquerda a camada corrigida, à direita a camada de localidade original

Resolvemos o problema da consistência topológica das localidades.

Para os mais puristas, uma explicação final sobre o problema da visualização das tabelas no DB Manager.

O problema não vem do QGIS, mas do padrão de geopackage.
O OGR (e o qgis) apenas procuram tabelas na tabela gpkg_contents. Para que sejam visíveis, é necessário acrescentar uma nova linha a essas tabelas:

INSERT INTO gpkg_contents (table_name, data_type) values (table_name,'attributes'). # attributes or features (if geometry); INSERT INTO gpkg_geometry (table_name, column_name, geometry_type_name, srs_id, z, m) (table_name, 'geom', 'Point', 4326, 1, 1);

Neste caso, no entanto, é de esperar que o QGIS DB Manager execute estas consultas automaticamente.

Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *