Çakışan özellikleri kaldırmak için ST_Difference mi kullanıyorsunuz?


11

PostGis 2.1 (ve Postgres SQL 9.3) kullanarak başka bir çokgen kümesi (test.single_geometry_1) herhangi bir alanı içermeyen çokgenler kümesi (işleme.trimmedparcelsnew) oluşturmak için ST_Difference kullanmaya çalışıyorum. İşte benim sorgu:

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;

Ancak ortaya çıkan çokgenler kırpılmamış, bunun yerine diğer katmanla kesiştikleri yerde bölünmüş gibi görünüyorlar. Sonucu bir tabloya ve aklınıza gelebilecek diğer her şeye koymadan seçimi çalıştırmayı denedim, ancak bu işlevi çalıştıramadım.

Sonucun bir resmini ekledim

resim açıklamasını buraya girin


Yorumlardan sonra, bir WHERE yan tümcesi eklemeyi denedim. Kesişme olmayan parseller ve diğer parsellerin kesişen alanlarının kaldırılmasını istiyorum (katman testi.single_geometry, parsellerimden çıkarılmasını istediğim kirliliği temsil ediyor). Bir kavşak denedim ama tabii ki aslında kavşakları istemiyorum, bu yüzden şimdi ayrılmaya çalışıyorum. Ben de benim tabloya orig eklemeyi denedim ama ST_Difference ( http://postgis.net/docs/ST_Difference.html ) belgelerini tam ihtiyacım geometri (A geometrisinin bu kısmını temsil eden bir geometri döndürür) diyor geometri B ile kesişmez), bu yüzden neden orijinal çokgeni masamda neden isteyeceğim konusunda kafam karıştı. Her neyse, işte benim değiştirilmiş kodum:

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);

Dbaston'un cevabından sonra şimdi denedim:

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;

Bunun sonucu yalnızca test.multi_geometry_1 ürününün bir kopyasıdır. Gerçi şimdi bölünme gerçekleşmiyor.

Önceki sürümü denedim, ancak tekrar sadece test.multi_geometry_1 kopyasını alın:

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;

Yanlış yaptığım başka bir şey olup olmadığını merak etmeye başlıyorum? Devam eden ifade:

DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;

Ve ben PostgreSQL SQL sorgu penceresinden ve Openjump sorguları çalıştırıyorum.

Tabloyu görmek için kullandığım ifade:

SELECT * FROM processing.parcels_trimmed_no_coalesce;

Sadeleştirme açısından şimdi bu sorguyu aşağıya indirdim:

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;

Bu, istenen sonuç test.geometriestocutagainst'e kesilmiş orijinal olduğunda, yalnızca orijinal çokgenlerle (test.geometriestocut) sonuçlanır.


Bir WHEREcümle belirtmediniz , dolayısıyla ortaya çıkan tabloda polinom genişlemesi olabilir. Kaç satır var trimmedparcelsnew?
Vince

Yalnızca kesiştiği yer arasındaki farkı istiyorsanız, WHERE ST_Intersects (orig.geom, cont.geom) eklemeyi deneyebilirsiniz. Aksi takdirde, kesişmeyen iki çokgen arasındaki fark orijinal çokgendir.
John Powell

Kesilmiş parselde yeni 24 satır var, kesişmediklerinde bile farkı istiyorum, bu yüzden farktan ziyade tabloda orig.geom kullanmam gerektiğini düzeltir miyim?
Mart

Her özelliği - Bir ayrık testi polinom genişleme üretmelidir cont her özellik için bir kez görünmesine Orj örtüşme etmez ve fark edecektir asla bir giriş geometri değiştirmek
Vince

Tamam açıklama için teşekkürler, ama hala orijinal kod neden çalışmıyor emin değilim. ST_Difference (orig.geom, cont.geom) b ile kesişmeyen bir geometriyi döndürürse, tablo neden b ile kesişmeyen bir geometri yerine bölünmüş geometriyi içerir.
Mart

Yanıtlar:


14

Kendi kendine birleştirme , iki özellik çifti arasındaki ilişki üzerinde çalışmanıza olanak tanır . Ancak çiftlerle ilgilendiğinizi düşünmüyorum: her özellik için, bu özellik ile veri kümenizdeki diğer tüm özellikler arasındaki ilişki üzerinde çalışmak istersiniz . Bunu bir alt sorgu ifadesiyle gerçekleştirebilirsiniz:

CREATE TABLE parcels_trimmed AS
SELECT id, ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                FROM parcels b
                                WHERE ST_Intersects(a.geom, b.geom)
                                  AND a.id != b.id))
FROM parcels a;

Yine de sonuçlarda tuhaf bir şeyler görebilirsiniz. Çakışma olmayan parseller tamamen düşürülüyor! Bunun nedeni bu ST_Unionboş bir kayıt agrega olacak NULLve ST_Difference(geom, NULL)olduğu NULL. Bunu düzeltmek için, ST_Differenceçağrınızı a COALESCE:

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM parcels a;

Sonucu, eğer bu aracı ST_Differenceolup NULL, kaynaştırılmış ifade orijinal geometrisine değerlendirecektir.

Yukarıdaki sorgu, alanınızdaki çakışan alanları tamamen kaldıracaktır. Bunun yerine bir kazanan seçmek isterseniz a.id < b.id, yerine veya başka bir kriter yapabilirsiniz a.id != b.id.


Yanıt için teşekkürler, maalesef bunun benim için çalışmasını sağlamakta sorun yaşıyorum, bunun yerine orijinal çokgen (a) ile bitiyor. Sorumu daha fazla bilgi ile düzenleyeceğim. Tekrar teşekkürler.
Mart

2

Seninle aynı problemi yaşadım. Sorununuza zaten bir çözüm buldunuz mu bilmiyorum, ama yukarıdaki kabul edilen cevabı değiştirdim ve istediğimi aldım.

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Collect(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         )), a.geom)
FROM parcels a;

1

PostGIS Eklentilerinden ST_DifferenceAgg () kullanıyorum . İki tabloyu birleştirmek, benzersiz bir tanımlayıcı ve geometri sütununda bir dizin oluşturmak zorundasınız. Kısa bir örnek:

WITH overlappingtable AS (
  SELECT 1 id, ST_GeomFromText('POLYGON((0 1, 3 2, 3 0, 0 1), (1.5 1.333, 2 1.333, 2 0.666, 1.5 0.666, 1.5 1.333))') geom
  UNION ALL
  SELECT 2 id, ST_GeomFromText('POLYGON((1 1, 3.8 2, 4 0, 1 1))')
  UNION ALL
  SELECT 3 id, ST_GeomFromText('POLYGON((2 1, 4.6 2, 5 0, 2 1))')
  UNION ALL
  SELECT 4 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
  UNION ALL
  SELECT 5 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
)
SELECT a.id, ST_DifferenceAgg(a.geom, b.geom) geom
FROM overlappingtable a,
     overlappingtable b
WHERE a.id = b.id OR -- Make sure to pass at least once the polygon with itself
      ((ST_Contains(a.geom, b.geom) OR -- Select all the containing, contained and overlapping polygons
        ST_Contains(b.geom, a.geom) OR
        ST_Overlaps(a.geom, b.geom)) AND
       (ST_Area(a.geom) < ST_Area(b.geom) OR -- Make sure bigger polygons are removed from smaller ones
        (ST_Area(a.geom) = ST_Area(b.geom) AND -- If areas are equal, arbitrarily remove one from the other but in a determined order so it's not done twice.
         a.id < b.id)))
GROUP BY a.id
HAVING ST_Area(ST_DifferenceAgg(a.geom, b.geom)) > 0 AND NOT ST_IsEmpty(ST_DifferenceAgg(a.geom, b.geom));

Bu, örtüşen parçaları en büyük örtüşen çokgenle birleştirecektir. Çakışan parçayı ayrı tutmak istiyorsanız, ST_splitAgg () örneğine bakın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.