अतिव्यापी सुविधाओं को हटाने के लिए ST_Difference का उपयोग करना?


11

मैं PolyGons (प्रोसेसिंग.trimmedparcelsnew) का एक सेट बनाने के लिए ST_Difference का उपयोग करने की कोशिश कर रहा हूं, जिसमें पोस्टगिस 2.1 (और पोस्टग्रेज एसक्यूएल 9.3) के साथ पॉलीगोन (test.single_geometry_1) के एक और सेट द्वारा कवर किया गया कोई भी क्षेत्र शामिल नहीं है। यहाँ मेरी क्वेरी है:

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;

लेकिन परिणामी बहुभुजों को छंटनी नहीं की गई है, इसके बजाय वे विभाजित हो गए हैं जहां वे दूसरी परत के साथ अंतर करते हैं। मैंने केवल एक तालिका में परिणाम डाले बिना चयन को चलाने की कोशिश की है और बाकी सब कुछ जिसके बारे में मैं सोच सकता हूं, लेकिन मुझे यह काम करने के लिए नहीं मिल सकता है।

मैंने परिणाम की एक तस्वीर संलग्न की है

यहां छवि विवरण दर्ज करें


टिप्पणियों के बाद, मैंने WHERE क्लॉज जोड़ने की कोशिश की है। मैं चाहता हूं कि जिन पार्सल में कोई चौराहा नहीं है, और हटाए गए अन्य पार्सल के चौराहे वाले क्षेत्र (परत परीक्षण.सिंघल_गेमेट्री मैं अपने पार्सल से हटाए जाने वाले संदूषण का प्रतिनिधित्व करता हूं)। मैंने एक प्रतिच्छेदन की कोशिश की लेकिन निश्चित रूप से मैं वास्तव में गैर-चौराहों को चाहता हूं इसलिए मैं अब एक असहमति की कोशिश कर रहा हूं। मैंने अपनी तालिका में मूल को जोड़ने की भी कोशिश की है, लेकिन ST_Difference ( http://postgis.net/docs/ST_Difference.html ) के लिए प्रलेखन यह कहता है कि मुझे सटीक ज्यामिति चाहिए जो मुझे चाहिए (एक ज्यामिति जो ज्यामिति के उस हिस्से का प्रतिनिधित्व करती है जो ज्यामिति बी के साथ प्रतिच्छेद नहीं करता है), इसलिए मुझे भ्रम है कि मैं इसके बजाय मूल बहुभुज को अपनी तालिका में क्यों चाहूंगा। वैसे भी, यहाँ मेरा संशोधित कोड है:

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 के उत्तर के बाद मैंने अब कोशिश की है:

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;

इसका परिणाम सिर्फ test.multi_geometry_1 की एक प्रति है। हालांकि अब बंटवारा नहीं हो रहा है।

मैंने पहले संस्करण की कोशिश की थी, लेकिन फिर से 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;

मुझे आश्चर्य होने लगा है कि क्या कुछ और है जो मैं गलत कर रहा हूं? कार्यवाही कथन है:

DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;

और मैं PostgreSQL SQL क्वेरी विंडो और Openjump से क्वेरी चला रहा हूं।

तालिका देखने के लिए मैं जिस कथन का उपयोग करता हूं वह है:

SELECT * FROM processing.parcels_trimmed_no_coalesce;

सरलीकरण के हित में मैंने अब इस क्वेरी को घटाकर केवल:

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;

यह अभी भी सिर्फ मूल बहुभुज (test.geometriestocut) में परिणाम देता है जब वांछित परिणाम test.geometriestocutagainst के खिलाफ मूल छंटनी की जाती है।


आपने एक WHEREखंड निर्दिष्ट नहीं किया है , इसलिए आपको परिणामी तालिका में बहुपद विस्तार हो सकता है। कितने पंक्तियों में हैं trimmedparcelsnew?
विंस

यदि आप केवल उस अंतर को चाहते हैं जहां वे अंतर करते हैं, तो आप WHERE ST_Intersects (Orig.geom, cont.omom) को जोड़ने का प्रयास कर सकते हैं। अन्यथा, दो बहुभुज का अंतर जो अंतर नहीं करता है, मूल बहुभुज है।
जॉन पॉवेल

छंटनी किए गए पार्सल नए में 24 पंक्तियां हैं, मैं अंतर नहीं होने पर भी अंतर चाहता हूं, इसलिए क्या मैं सही करूंगा कि मुझे अंतर के बजाय तालिका में ओरिजनल का उपयोग करने की आवश्यकता है?
मार्ट

में प्रत्येक सुविधा - एक संबंध तोड़ना परीक्षण बहुपद विस्तार का उत्पादन करना चाहिए शेष भाग में हर सुविधा के लिए एक बार प्रकट करने के लिए मूल कि ओवरलैप नहीं करता है, और अंतर होगा कभी नहीं एक इनपुट ज्यामिति बदल
विन्स

स्पष्टीकरण के लिए ठीक है धन्यवाद, लेकिन मुझे अभी भी यकीन नहीं है कि मूल कोड क्यों काम नहीं कर रहा है। यदि ST_Difference (Orig.geom, cont.geom) में ज्यामिति लौटाता है जिसमें ख के साथ अंतर नहीं होता है, तो तालिका में विभाजित ज्यामिति के बजाय तालिका में ज्यामिति क्यों नहीं होती है।
मार्ट

जवाबों:


14

एक आत्म-जुड़ाव आपको दो विशेषताओं के जोड़े के बीच संबंधों पर काम करने की अनुमति देता है। लेकिन मुझे नहीं लगता कि आप जोड़े में रुचि रखते हैं: प्रत्येक सुविधा के लिए, आप उस विशेषता और अपने डेटासेट में अन्य सभी सुविधाओं के बीच संबंध पर काम करना चाहते हैं । आप इसे एक सूक्ष्म अभिव्यक्ति के साथ पूरा कर सकते हैं:

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;

आप परिणामों में कुछ अजीब देख सकते हैं, हालांकि। जिन पार्सल में कोई ओवरलैप नहीं है उन्हें पूरी तरह से गिराया जा रहा है! ऐसा इसलिए है क्योंकि ST_Unionएक खाली रिकॉर्डसेट पर एग्रीगेट होने जा रहा है NULL, और ST_Difference(geom, NULL)है NULL। इसे खत्म करने के लिए, आपको अपने ST_Differenceकॉल को एक में लपेटना होगा 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;

इसका अर्थ यह है कि यदि परिणाम ST_Differenceहै NULL, तो सहवर्ती अभिव्यक्ति मूल ज्यामिति का मूल्यांकन करेगी।

उपरोक्त क्वेरी आपके डोमेन से अतिव्यापी क्षेत्रों को पूरी तरह से हटा देगी। यदि आप इसके बजाय एक विजेता चुनना चाहते हैं, तो आप इसके बजाय a.id < b.id, या कुछ अन्य मानदंड कर सकते हैं a.id != b.id


प्रतिक्रिया के लिए धन्यवाद, दुर्भाग्यवश मुझे इसके लिए काम करने में परेशानी हो रही है, इसके बजाय मूल बहुभुज (ए) के साथ समाप्त हो रहा है। मैं अपने प्रश्न को अधिक जानकारी के साथ संपादित करूंगा। एक बार फिर धन्यवाद।
मार्ट

2

मुझे आप जैसी ही समस्या थी। मुझे नहीं पता कि क्या आपको पहले से ही अपनी समस्या का हल मिल गया है, लेकिन मैंने ऊपर दिए गए स्वीकृत उत्तर को संशोधित कर दिया और मुझे वह मिल गया जो मैं चाहता था।

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 Addons से ST_DifferenceAgg () का उपयोग करता हूं । आपको दो तालिकाओं को एक साथ मिलाना होगा, एक विशिष्ट पहचानकर्ता और ज्यामिति स्तंभ पर एक सूचकांक बनाना होगा। यहाँ एक छोटा उदाहरण दिया गया है:

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

यह अतिव्यापी बहुभुज के साथ अतिव्यापी भागों को मर्ज करेगा। यदि आप ओवरलैपिंग भाग को अलग रखना चाहते हैं तो ST_splitAgg () उदाहरण देखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.