मल्टी-ज्यामिति से भंग बफर बनाएं (साझा विशेषता और स्थानिक अंतर द्वारा संघ)


10

मुझे मल्टी-पॉइंट इनपुट सुविधाओं से भंग बफ़र्स बनाने हैं। नीचे दिए गए उदाहरण में, इनपुट तालिका में 4 विशेषताएं हैं। फ़ीचर #2में दो बिंदु ज्यामितीय होते हैं। एक बफर बनाने के बाद, मुझे 4 बहुभुज ज्यामितीय मिलते हैं:

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

क्या परिणाम को समूहीकृत करने का कोई तरीका है? अंकों की बफ़र्स #1और #2भंग कर रहे हैं और एक भी बहु बहुभुज विशेषता किया जाना चाहिए ( a)।

मैंने अब तक क्या किया है:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/) AS geom
FROM
public.multipoints)
AS sub_qry;

संपादित करें:

-- create sample geometries

CREATE TABLE public.multipoints (
gid serial NOT NULL,
geom geometry(MultiPoint, 31256),
CONSTRAINT multipoints_pkey PRIMARY KEY (gid)
);

CREATE INDEX sidx_multipoints_geom
ON public.multipoints
USING gist
(geom);

INSERT INTO public.multipoints (gid, geom) VALUES
(1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),
(2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),
(3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
(4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256));

आप उपश्रेणियों का बहुत अधिक उपयोग करते हैं। यह जिस पर आप क्लस्टर करना चाहते हैं उस विशेषता पर GROUP BY के लिए आपकी क्षमता को समाप्त कर देता है।
विंस

तो आपको एक स्थानिक संघ करने की आवश्यकता है और फिर सुविधा संख्या के आधार पर एक संघ भी है, यही कारण है कि आप ऊपर दिए गए आरेख से 3 बहुपदों की अपेक्षा करते हैं। मुझे संदेह है कि इसके लिए दो-चरणीय प्रक्रिया की आवश्यकता होगी, लेकिन उत्तर देने से पहले, प्रश्न पर स्पष्ट होना चाहता था।
जॉन पॉवेल

हां, मैं बफर पॉलीगनों को संघ बनाना चाहता हूं और इनपुट सुविधाओं की संख्या के आधार पर परिणाम एकत्र करता हूं।
ग्रहण

इस पर किसी भी अद्यतन? मैं जानना चाहूंगा कि क्या यह आपके लिए काम करता है, जहां तक ​​मैं देख सकता हूं, मैंने सवाल का जवाब दिया है।
जॉन पॉवेल

देर से जवाब के लिए क्षमा करें, मैं कुछ दिनों के लिए ऑनलाइन नहीं है।
ग्रहण

जवाबों:


7

ओपी की छवि में उन लोगों की नकल करने के लिए कुछ यादृच्छिक बिंदुओं के साथ शुरू करना, जहां पहले दो स्थानिक रूप से प्रतिच्छेद होता है, फिर 2 और 3 में एक ही विशेषता आईडी (2) होती है, कुछ अन्य बिंदुओं के साथ जो न तो स्थानिक रूप से प्रतिच्छेद करते हैं और न ही एक ही विशेषता, निम्नलिखित क्वेरी 3 क्लस्टर का उत्पादन करती है:

WITH 
  temp (id, geom) AS 
     (VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
        (2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
        (2, ST_Buffer(ST_MakePoint(10, 10), 2)), 
        (3, ST_Buffer(ST_MakePoint(-2, 12), 2)), 
        (4, ST_Buffer(ST_MakePoint(5, -6), 2))),
 unions(geoms) AS 
      (SELECT ST_Union(geom) FROM temp GROUP BY id),
 clusters(geoms) AS 
      (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
         FROM unions),
 multis(id, geoms) AS 
      (SELECT row_number() over() as id, geoms FROM clusters)
 SELECT ST_UNION(d.geom) FROM 
      (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

यहाँ कई चरण हैं:

  1. उपयोग ST_Union, आईडी द्वारा समूहीकरण, विशेषता द्वारा पहले समूह के लिए
  2. ST_ClusterIntersectingएक ही समूह से उन लोगों को संयोजित करने के लिए उपयोग करें जो स्थानिक रूप से प्रतिच्छेद करते हैं
  3. प्रत्येक क्लस्टर में एक आईडी जोड़ें (टेबल मल्टीस) - क्लस्टरस्टर इन्टरसेक्टिंग में सीधे ऐसा करने की कोशिश करने से सभी ज्यामितीय 1 की आईडी प्राप्त करते हैं।
  4. चरण 2 से डंप किए गए ज्यामितीय संघ, चरण 3 से आईडी द्वारा समूहीकरण - यह भंग हिस्सा है। यह आपके क्लस्टर ए में दो ओवरलैपिंग बहुभुज का कारण बनता है, ओवरलैपिंग के बजाय एक साथ शामिल होने के लिए, जैसा कि वे चरण 2 के अंत में हैं।

बल्कि लंबा है, लेकिन यह काम करता है (और, मुझे यकीन है कि एक छोटा रास्ता है)।

क्यूजीआईएस में डब्ल्यूकेटी टूल का उपयोग करना, (और यह पता लगाना कि मैं संपादन टूल के साथ कितना भयानक हूं) निम्नलिखित जैसे क्लस्टर का उत्पादन करता है, जहां आप क्लस्टर को अपने लेबल के रूप में देख सकते हैं, यह सब एक साथ है - यानी, एक रंग।

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

यदि आप अंतिम, ST_UNION (d.geom) के लिए एक ST_AsText राउंड लगाते हैं, तो आप सीधे परिणाम देख सकते हैं।

EDIT टिप्पणियों में अधिक जानकारी के बाद: जैसा कि आप बिंदुओं के साथ शुरू कर रहे हैं, आपको बफर को मेरे मूल समाधान में शामिल करना होगा - जिसे मैंने अपने आरेख की नकल करने के लिए शुरुआत में अस्थायी सीटीई में डाल दिया था। यूनियनों सीटीई में बफर को जोड़ना आसान होगा, इसलिए आप एक ही बार में सभी ज्यामितीय कार्य कर सकते हैं। इसलिए, एक उदाहरण के रूप में, 1000 की बफर दूरी का उपयोग करते हुए, निम्नलिखित अब अपेक्षित रूप से 3 क्लस्टर लौटाता है।

WITH temp(id, geom) AS 
  (VALUES 
      (1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),   
      (2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),                                                
      (3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
      (4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256))
),                                              
unions(geoms) AS 
  (SELECT st_buffer(ST_Union(geom), 1000) FROM temp GROUP BY id),
clusters(geoms) AS 
  (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
     FROM unions),
multis(id, geoms) AS 
  (SELECT row_number() over() as id, geoms FROM clusters)
SELECT id, ST_UNION(d.geom) FROM 
  (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

क्षमा करें आपको वापस आने में इतना समय लगा। मुझे QGIS में बफर ज्यामिति की कल्पना करने में कुछ परेशानी है। मैंने आपकी क्वेरी का उपयोग करके संशोधित करने का प्रयास किया है ST_SetSRID, ST_Multiऔर ::geometry(Multipolygon, /*SRID*/), लेकिन फिलहाल यह काम नहीं कर रहा है।
ग्रहण

ठीक है, यदि आप अपना कोड पोस्ट कर सकते हैं, और इससे भी बेहतर कुछ डेटा, मैं मदद करने में सक्षम हो सकता हूं।
जॉन पॉवेल

मैंने नमूना बिंदु बनाने के लिए कुछ SQL जोड़ा है।
ग्रहण

आज थोड़ा सा बंधा हुआ है, मैं जितनी जल्दी हो सके वापस आ जाऊंगा। बहुस्तरीय को क्वेरी में भी काम करना होगा।
जॉन पॉवेल

3

ऐसा करने का एक तरीका ST_Unionसभी बफ़र्स के साथ है, ST_Dumpपरिणामी बहुभुज के घटकों को प्राप्त करने के लिए, और ST_Intersectsइनपुट बिंदुओं के साथ वापस जुड़ने के लिए यह पता लगाना है कि प्रत्येक क्लस्टर में कितने / कौन से अंक बने।

यह कॉल करने से पहले बिंदुओं को एक साथ जोड़कर शामिल होने की आवश्यकता के बिना किया जा सकता है ST_Buffer। समान विघटित बफर के भीतर स्थित होने के लिए दो बिंदुओं के लिए, उन्हें किसी दूरी से कम के बिंदुओं के बीच हॉप्स द्वारा पहुंच योग्य होना चाहिए eps। यह केवल एक न्यूनतम-लिंकेज क्लस्टरिंग समस्या है, जिसका उपयोग करके हल किया जा सकता है ST_ClusterDBSCAN:

SELECT
  cluster_id,
  ST_Union(ST_Buffer(geom, 1000)) AS geom,
  count(*)                        AS num_points,
  array_agg(point_id)             AS point_ids
FROM (
  SELECT
    point_id,
    ST_ClusterDBSCAN(geom, eps := 2000, minpoints := 1) OVER() AS cluster_id ,
    geom
  FROM points) sq
 GROUP BY cluster_id;

ध्यान दें कि यह बफर-प्रथम विधि के समान परिणाम नहीं देगा, क्योंकि PostGIS बफ़र्स सही सर्कल नहीं हैं और दो अंक 1000 मीटर के अलावा दो 500 मी बफ़र्स द्वारा कनेक्ट नहीं किए जा सकते हैं।


लगता है कि हमारे पास एक समान विचार था। मैंने तुम्हारा परीक्षण नहीं किया है, लेकिन मुझे यकीन है कि यह काम करता है, और मेरी तुलना में अधिक सफाई से।
जॉन पॉवेल

ऐसा लगता है कि PostGIS 2.2.1 ST_ClusterDBSCAN का समर्थन नहीं करता है। मैंने PostGIS 2.3.2 स्थापित किया है, लेकिन pgAdmin में नए पोस्टगिस एक्सटेंशन अभी भी 2.2.1 संस्करण हैं।
ग्रहण

0

इस उत्तर के अनुसार आप अपनी उपश्रेणी के भीतर ST_DUMP करना चाहते हैं।

कुछ इस तरह:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/)) AS geom
FROM
public.multipoints)
AS sub_qry;

इसका कारण यह है कि ST_UNIONसभी विशेषताओं का एक घुलित ST_DUMPबहुभुज लौटाता है, और इसे अलग-अलग बहुभुज सुविधाओं (जो भंग कर दिया गया था) में तोड़ देता है।


1
यह वास्तव में काम नहीं करेगा, क्योंकि वांछित मल्टीपर्ट बहुभुज को क्लस्टर करने के लिए आवश्यक किसी भी विशेषताओं को खो दिया जाएगा।
विंस

मैंने कोशिश की है ST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom, लेकिन यह 3 के बजाय 4 सुविधाएँ बनाता है
eclipsed_by_the_moon

ओह, ठीक है, आप संख्या द्वारा समूह बनाना चाहते हैं? आपको GROUP_BYपहले की आवश्यकता होगी ST_UNION
एलेक्स लीथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.