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

Para aqueles que não estão familiarizados com as alegrias de trabalhar com o cadastro francês, devem saber que, se tiverem a oportunidade de trabalhar com dados cadastrais correspondentes a “Lieux-dits” (uma subdivisão de comunas), verificarão que a coerência espacial (topologia) não é realmente 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, veremos como resolver ambos os problemas:

  • Como corrigir a topologia da camada de localidade removendo os polígonos sobrepostos e os espaços vazios entre eles;
  • Como recriar uma camada comum que seja consistente com a nova camada de localidade e que se sobreponha exatamente aos limites da localidade.

O exemplo abaixo foi criado com base nos dados do registo cadastral oficial do departamento 71, descarregado a partir da seguinte ligação 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 necessita de uma base de dados PostgreSQL/Postgis. É possível adaptá-la ao SQLite para utilizar um ficheiro geopackage e o QGis DB Manager. Mas é preciso contar com tempos de processamento muito longos e contornar algumas deficiências e bugs. Vamos ver a melhor solução aqui, mas apresentaremos a solução com o Geopackage noutro artigo.

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

Para gerir os espaços entre polígonos, ainda que algumas ferramentas de snapping possam resolver 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 pelo menos 2-3 metros.

Escolha um ficheiro de saída permanente no formato Geopackage, que lhe permitirá seguir o procedimento no passo seguinte 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 as sobreposições.

2- Carregar o layer lieux-dits no PostgreSQL

Pode seguir os pormenores de como carregar a camada no artigo Como carregar um geopackage no Postgis com o QGis . Utiliza-se o mesmo procedimento para carregar shapefiles.

E encontra a sua tabela no PostreSQL com o pgAdmin

3- Executar o script SQL

Vamos utilizar um único script para fazer todo o trabalho:

  1. Criamos 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 outros polígonos.
  3. As partes que se sobrepõem são mantidas na segunda coleção
  4. Acrescentamos a parte sobreposta ao mais pequeno dos dois polígonos afectados pela sobreposição

O guião é o seguinte:

DROP TABLE IF EXISTS table_corrigee ; 

CREATE OR REPLACE VIEW auto_jointure AS SELECT

    tampon.id as id,
    tampon.nom as "nom",
    tampon.commune as "commune",
-- recuperamos todos os polígonos da tabela de buffer em duas colecções: uma onde temos as geometrias completas e outra onde temos 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 dos polígonos 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 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 ;
/*
Vamos criar uma tabela com 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 são contíguos, 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, removendo assim as partes em conflito*/
    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)
/*As intersecções acabadas de subtrair devem ser adicionadas 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);
/*Uma chave primária é então redefinida para que o QGIS possa carregar a camada*/

ALTER TABLE table_corrigee ADD CONSTRAINT pk_table_corrigee PRIMARY KEY (id);

Para adaptar o guião ao seu caso, é necessário utilizar um processador de texto para substituir os seguintes elementos

  • todas as ocorrências de tampon pelo nome da sua tabela que contém os buffers de geometria,
  • todas as ocorrências de table_corrigee pelo nome da tabela de resultados que pretende,
  • e verifique se o identificador da sua tabela com buffer é id. Por defeito, pode ter o nome fid. Neste caso, substitua todas as ocorrências de id por fid.

Carregue esta nova camada no QGis:

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

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

Como recriar uma camada de comunas que seja coerente com a nova camada de lieux-dits

Se sobrepusermos a nossa nova camada com os limites das comunas do cadastro, podemos ver que não são coerentes com as nossas novas localidades, tal como não são coerentes com as localidades originais.

Para obter fronteiras comunais coerentes, bastaria agrupar as localidades por comuna. O problema é que nem todas as áreas comunais estão divididas em localidades. Por conseguinte, existem “lacunas” na camada de localidade, o que é perfeitamente normal.

Para construir comunas completas, é necessário primeiro criar os polígonos em falta para as localidades, atribuir o código de comuna correspondente e, em seguida, agrupar as localidades utilizando o atributo de comuna.

1-Criação dos polígonos em falta

Em primeiro lugar, vamos criar uma nova camada de polígonos, direito de passagem, com um único polígono que envolve completamente a nossa camada de localidade.

De seguida, utilizamos o tratamento “Diferença” para manter na nossa tabela corrigida apenas as zonas de direito de passagem que não correspondem às localidades existentes:

Pode deixar o resultado dos tratamentos como camadas temporárias porque não terá mais nenhuma utilização para elas depois do resultado final.

O resultado da diferença é:

O resultado é um único multipolígono. Antes de continuar, temos de converter esta camada multipolígono em polígonos simples, para podermos remover o contorno da área.

Utilizamos o processamento de peça única e peça múltipla

Quando o processamento estiver concluído, passe o resultado para o modo de edição e seleccione o polígono exterior.

E estamos a acabar com ele:

Assim, temos agora uma camada de Geometrias Simples que contém todos os locais onde não existem localidades e uma camada de localidades corrigidas. Fundimos as duas camadas numa única camada sem lacunas:

Ainda temos de resolver o problema dos atributos dos polígonos que não são localidades. Estes precisam de ter um atributo que contenha o código da comuna, para que possam ser agrupados por comuna.

Vamos utilizar a camada de comunas do registo predial e efetuar uma junção por localidade com a nova camada fundida.

Temos agora a tabela em anexo:

Nesta imagem, temos os primeiros cinco registos correspondentes a áreas que não são localidades. O atributo comuna, que nos interessa para o passo seguinte, não está preenchido, mas o atributo id2, que provém da união por localidade com a camada de comunas, está corretamente preenchido.

Abra a tabela no modo de edição. Utilize uma expressão para selecionar os registos que não têm o atributo comuna preenchido e, em seguida, abra a calculadora de campos e actualize o campo comuna com o conteúdo de id2.

Agora podemos agrupar as localidades por comuna para obter a nossa camada de comunas que é coerente com as localidades.

Utilizamos o tratamento Grupo, com a camada resultante da junção que acabámos de modificar.

Então temos as nossas novas comunas. Resta apenas uma última operação a efetuar. Como em qualquer operação de fusão, o resultado conterá uma série de pequenas impurezas que precisam de ser eliminadas:

Para o fazer, vamos utilizar o tratamento Remover buracos.

Não se esqueça de guardar o resultado num ficheiro permanente – seria difícil ter de refazer tudo!

Podemos agora comparar o resultado da nossa nova camada comum com a camada original

À esquerda está a camada cadastral original, à direita a camada que construímos

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 *