Estou tentando usar ST_Difference para criar um conjunto de polígonos (processing.trimmedparcelsnew) que não contêm nenhuma área coberta por outro conjunto de polígonos (test.single_geometry_1) usando o PostGis 2.1 (e o Postgres SQL 9.3). Aqui está a minha consulta:
CREATE TABLE processing.trimmedparcelsnew AS
SELECT
orig.id, ST_Difference(orig.geom, cont.geom) AS difference
FROM
test.single_geometry_1 cont,
test.multi_geometry_1 orig;
Mas os polígonos resultantes não foram aparados; eles parecem ter sido divididos onde se cruzam com a outra camada. Tentei apenas executar o select sem colocar o resultado em uma tabela e tudo o mais em que consigo pensar, mas não consigo fazer essa função funcionar.
Anexei uma foto do resultado
Após os comentários, tentei adicionar uma cláusula WHERE. Quero que as parcelas que não têm interseções e as áreas de interseção das outras parcelas sejam removidas (a camada test.single_geometry representa a contaminação que eu quero remover das minhas parcelas). Eu tentei uma interseção, mas é claro que eu realmente quero as não interseções, então agora estou tentando uma desconexão. Também tentei adicionar o orig à minha tabela, mas a documentação para ST_Difference ( http://postgis.net/docs/ST_Difference.html ) diz que ele retorna a geometria exata que eu preciso (uma geometria que representa essa parte da geometria A que não se cruza com a geometria B); portanto, estou confuso sobre o motivo pelo qual desejaria o polígono original na minha tabela. Enfim, aqui está o meu código modificado:
CREATE TABLE processing.trimmedparcelsnew AS
SELECT
orig.id, ST_Difference(orig.geom, cont.geom) AS difference, orig.geom AS geom
FROM
test.single_geometry_1 cont,
test.multi_geometry_1 orig
WHERE ST_Disjoint(orig.geom, cont.geom);
Seguindo a resposta do dbaston, tentei agora:
CREATE TABLE processing.parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.single_geometry_1 b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;
O resultado disso é apenas uma cópia do test.multi_geometry_1. Embora agora a divisão não esteja mais ocorrendo.
Eu tentei a versão anterior, mas novamente é só pegar uma cópia do test.multi_geometry_1:
CREATE TABLE processing.parcels_trimmed_no_coalesce AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.single_geometry_1 b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;
Estou começando a me perguntar se há algo mais que estou fazendo errado? A declaração de processo é:
DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;
E estou executando as consultas na janela de consulta SQL do PostgreSQL e no Openjump.
A declaração que eu uso para ver a tabela é:
SELECT * FROM processing.parcels_trimmed_no_coalesce;
No interesse da simplificação, reduzi agora essa consulta para apenas:
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom)
FROM test.geometriestocutagainst b
WHERE ST_Intersects(a.geom, b.geom)
AND a.id != b.id)), a.geom)
FROM test.geometriestocut a;
Isso ainda resulta apenas nos polígonos originais (teste.geometriestocut) quando o resultado desejado é o original aparado em comparação com teste.geometriestocut.
WHERE
cláusula, portanto, pode haver expansão polinomial na tabela resultante. Quantas linhas estãotrimmedparcelsnew
?Respostas:
Uma união automática permite que você opere no relacionamento entre pares de dois recursos. Mas não acho que você esteja interessado em pares: para cada recurso, você deseja operar o relacionamento entre esse recurso e todos os outros recursos do seu conjunto de dados. Você pode fazer isso com uma expressão de subconsulta:
Você pode ver algo estranho nos resultados, no entanto. As encomendas que não possuem sobreposições estão sendo totalmente descartadas! Isso
ST_Union
ocorre porque o agregado em um conjunto de registros vazio seráNULL
eST_Difference(geom, NULL)
éNULL
. Para suavizar isso, você precisa encerrar suaST_Difference
chamada emCOALESCE
:Isso significa que, se o resultado de
ST_Difference
forNULL
, a expressão coalescente será avaliada para a geometria original.A consulta acima removerá totalmente as áreas sobrepostas do seu domínio. Se preferir escolher um vencedor, você pode fazer
a.id < b.id
, ou algum outro critério, em vez dea.id != b.id
.fonte
Eu tive o mesmo problema que você. Não sei se você já encontrou uma solução para o seu problema, mas modifiquei a resposta aceita acima e consegui o que queria.
fonte
Eu uso ST_DifferenceAgg () dos PostGIS Addons . Você precisa mesclar as duas tabelas, ter um identificador exclusivo e um índice na coluna de geometria. Aqui está um pequeno exemplo:
Isso mesclará as partes sobrepostas com o maior polígono sobreposto. Se você deseja manter a parte sobreposta separada, veja o exemplo ST_splitAgg ().
fonte