किसी भी और सभी आसन्न बहुभुजों को मिलाएं


22

मैं एक पार्सल (बहुभुज) परत पर आसन्न परीक्षण करना चाहता हूं और उन्हें विलय कर दूंगा यदि वे कुछ मानदंडों को फिट करते हैं (आकार हो सकता है)। नीचे दी गई तस्वीर के अनुसार, मैं पॉलीगन्स 1,2,3 और 4 का विलय करना चाहूंगा, लेकिन 5 नहीं

मुझे दो समस्याएं हैं:

  1. ST_TOUCHESTRUE लौटाता है यदि केवल कोने स्पर्श करते हैं, रेखा खंड नहीं। मुझे लगता है कि मुझे साझा लाइन सेगमेंट की जाँच करने के लिए ST_RELATE की आवश्यकता है।
  2. आदर्श रूप से, मैं सभी आसन्न बहुभुजों को एक में मिलाना चाहूंगा, लेकिन मुझे यकीन नहीं है कि कैसे दो से परे पैमाने पर - जैसे, एक दौर में 1,2,3 और 4 (और संभवतः वास्तविक डेटा पर अधिक) मर्ज करें।

मेरे पास अब जो संरचना है वह एक स्व-जुड़ाव पर आधारित है ST_TOUCHES

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

खिलौना डेटा

CREATE TABLE testpoly AS 
SELECT 
1 AS id, ST_PolyFromText('POLYGON ((0 0, 10 0, 10 20, 00 20, 0 0 ))') AS geom UNION SELECT
2 AS id, ST_PolyFromText('POLYGON ((10 0, 20 0, 20 20, 10 20, 10 0 ))') AS geom UNION SELECT
3 AS id, ST_PolyFromText('POLYGON ((10 -20, 20 -20, 20 0, 10 0, 10 -20 ))') AS geom UNION SELECT
4 AS id, ST_PolyFromText('POLYGON ((20 -20, 30 -20, 30 0, 20 0, 20 -20 ))') AS geom  UNION SELECT 
5 AS id, ST_PolyFromText('POLYGON ((30 0, 40 0, 40 20, 30 20, 30 0 ))') AS geom ;

चयन

SELECT 
    gid, adj_gid,
    st_AStext(st_union(l2.g1,l2.g2)) AS geo_combo
from (
    --level 2
    SELECT
      t1.id AS gid,
      t1.geom AS g1,
      t2.id AS adj_gid,
      t2.geom AS g2
     from
      testpoly  t1,
      testpoly  t2
     where
      ST_Touches( t1.geom, t2.geom ) 
      AND t1.geom && t2.geom 
) 
l2

यहाँ उत्पादन है:

+-----+---------+-------------------------------------------------------------------------------+
| gid | adj_gid | geo_combo                                                                     |
+-----+---------+-------------------------------------------------------------------------------+
| 1   | 2       | POLYGON((10 0,0 0,0 20,10 20,20 20,20 0,10 0))                                |
+-----+---------+-------------------------------------------------------------------------------+
| 1   | 3       | MULTIPOLYGON(((10 0,0 0,0 20,10 20,10 0)),((10 0,20 0,20 -20,10 -20,10 0)))   |
+-----+---------+-------------------------------------------------------------------------------+
| 2   | 1       | POLYGON((10 20,20 20,20 0,10 0,0 0,0 20,10 20))                               |
+-----+---------+-------------------------------------------------------------------------------+
| 2   | 3       | POLYGON((10 0,10 20,20 20,20 0,20 -20,10 -20,10 0))                           |
+-----+---------+-------------------------------------------------------------------------------+
| 2   | 4       | MULTIPOLYGON(((20 0,10 0,10 20,20 20,20 0)),((20 0,30 0,30 -20,20 -20,20 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 3   | 1       | MULTIPOLYGON(((10 0,20 0,20 -20,10 -20,10 0)),((10 0,0 0,0 20,10 20,10 0)))   |
+-----+---------+-------------------------------------------------------------------------------+
| 3   | 2       | POLYGON((20 0,20 -20,10 -20,10 0,10 20,20 20,20 0))                           |
+-----+---------+-------------------------------------------------------------------------------+
| 3   | 4       | POLYGON((20 -20,10 -20,10 0,20 0,30 0,30 -20,20 -20))                         |
+-----+---------+-------------------------------------------------------------------------------+
| 4   | 2       | MULTIPOLYGON(((20 0,30 0,30 -20,20 -20,20 0)),((20 0,10 0,10 20,20 20,20 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 4   | 3       | POLYGON((20 0,30 0,30 -20,20 -20,10 -20,10 0,20 0))                           |
+-----+---------+-------------------------------------------------------------------------------+
| 4   | 5       | MULTIPOLYGON(((30 0,30 -20,20 -20,20 0,30 0)),((30 0,30 20,40 20,40 0,30 0))) |
+-----+---------+-------------------------------------------------------------------------------+
| 5   | 4       | MULTIPOLYGON(((30 0,30 20,40 20,40 0,30 0)),((30 0,30 -20,20 -20,20 0,30 0))) |
+-----+---------+-------------------------------------------------------------------------------+

ध्यान दें कि बहुभुज आईडी = 3 आईडी = 1 के साथ एक बिंदु साझा करता है और इस प्रकार एक सकारात्मक परिणाम के रूप में वापस किया जाता है। अगर मैं WHERE क्लॉज को बदल देता हूं तो मुझे ST_Touches( t1.geom, t2.geom ) AND t1.geom && t2.geom AND ST_Relate(t1.geom, t2.geom ,'T*T***T**');कोई रिकॉर्ड नहीं मिलता है।

  1. तो सबसे पहले , मैं यह सुनिश्चित करने के लिए ST_Relate निर्दिष्ट करता हूं कि केवल पार्सल एक पंक्ति खंड साझा करने पर विचार किया जाता है।

  2. और फिर, मैं एक दौर में बहुभुज 1,2,3,4 को कैसे विलीन करूंगा, उपरोक्त कॉल से परिणाम को ध्वस्त करते हुए, सभी आसन्न 1 से 2 को पहचानते हुए रिवर्स के समान है?

अद्यतन करें

यदि मैं इसे whereक्लॉज में जोड़ता हूं तो मुझे स्पष्ट रूप से केवल बहुभुज मिलते हैं, न कि मल्टीप्लगॉन, इस प्रकार मेरे उद्देश्यों के लिए झूठी सकारात्मकता को बाहर निकालते हुए - कोने के स्पर्शों को नजरअंदाज कर दिया जाएगा।

GeometryType(st_union(t1.geom,t2.geom)) != 'MULTIPOLYGON'

हालांकि यह आदर्श नहीं है (मैं ST_RELATEअधिक सामान्य समाधान के रूप में टोपोलॉजी जांच का उपयोग करूंगा ), यह एक रास्ता है। फिर इन्हें डी-डुइंग और यूनियन करने की बात बनी हुई है। संभवतः, यदि मैं केवल बहुभुज को छूने के लिए एक अनुक्रम उत्पन्न कर सकता था, तो मैं उस पर संघ कर सकता था।

अपडेट II

यह एक बहुभुज साझाकरण लाइनों (लेकिन कोनों नहीं) का चयन करने के लिए काम करता है और इस प्रकार उपरोक्त MULTIPOLYGONपरीक्षण से अधिक सामान्य समाधान है । मेरा जहां खंड अब इस तरह दिखता है:

WHERE
              ST_Touches( t1.geom, t2.geom ) 
              AND t1.geom && t2.geom 

              -- 'overlap' relation
              AND ST_Relate(t1.geom, t2.geom)='FF2F11212') t2 

अब जो बचा हुआ है वह अभी भी बहुपत्नी की जोड़ी से अधिक के लिए मर्ज कैसे किया जा सकता है, लेकिन एक मनमाना संख्या के लिए मानदंड फिटिंग, एक बार में।


2
मुझे यकीन है कि ST_Relate सही तरीका है। मैंने एक समान समस्या को हल करके जाँच की कि एकल बिंदु चौराहों को बाहर करने के लिए चौराहों की लंबाई शून्य से अधिक थी। एक हैक, लेकिन काम करता है।
जॉन पॉवेल

अगर कोई समूह के लिए एक रास्ता था एक साथ विन्यास में सन्निहित बहुभुज आप तो संशोधित कर सकते ST_IntersectionArray: [समारोह] [1] ST_Union [1] के साथ काम करने के लिए gis.stackexchange.com/a/60295/36886
राफेल

2
समूहीकरण एक साथ सटे बहुभुज के बारे में, आप नीचे-ऊपर एल्गोरिथ्म क्लस्टरिंग मैं यहाँ लिखा था (संशोधित कर gis.stackexchange.com/a/115715/36886 अंतरिक्ष निकटता के बजाय के लिए परीक्षण करने के लिए) और फिर ST_Union का उपयोग करते हुए, जिसके परिणामस्वरूप cluster_ids पर समूहीकरण
राफेल

3
वहाँ भी ST_ClusterIntersectimg है जो आप की आवश्यकता हो सकती है। आपको पोस्टगिस 2.2
जॉन पॉवेल

जवाबों:


3

मैं यह सोचने में मदद नहीं कर सका कि आपका उदाहरण वास्तव में एक रेखापुंज है और यद्यपि आपने उल्लेख किया है कि आप "कुछ मानदंडों (आकार का हो सकता है) के आधार पर विलय करना चाहेंगे" मैं इसे रेखापुंज रूपांतरण के साथ एक शॉट देना चाहूंगा।

आपके विशिष्ट उदाहरण के लिए यह काम करेगा:

WITH rast AS (
  SELECT 
  ST_UNION(ST_AsRaster(geom,10, 20, '2BUI')) r
  FROM testpoly 
)
,p AS (
    SELECT (ST_DumpAsPolygons(r)).geom FROM rast
)
SELECT t.id,p.* 
FROM p
LEFT JOIN testpoly  t ON ST_Equals(p.geom, t.geom)

क्या होता है कि चूंकि आपके बहुभुज पूरी तरह से संरेखित कोशिकाएं हैं, वे अच्छी तरह से एक रेखापुंज (10x20 कोशिकाओं) में बदल देंगे। डंपस्पॉलीगोंस यहां आपको आसन्न सभी कोशिकाओं को एक में विलय करने में मदद करता है और मूल बहुभुजों के साथ तुलना करके आप आईडी को गैर-मर्ज किए गए पॉली के लिए वापस लाने में सक्षम होंगे।

इसकी व्याख्या करने के बाद, मैं बहुत उत्सुक हूं कि यह कैसे स्केल होगा और आपका डेटासेट कितना बड़ा है: D


चतुर विचार। यह एक खिलौना उदाहरण है, हालांकि - मेरा वास्तविक डेटा एक पार्सल परत है जो बड़े पैमाने पर रेखापुंज के लिए मैप नहीं करेगा।
एको

3

हुड के नीचे कई पास के साथ प्रक्रियात्मक शैली में ऐसा करने का एक उदाहरण यहां दिया गया है।

CREATE TABLE joined_testpoly AS SELECT array[id] ids, geom FROM testpoly; 

आपको अधिक स्तंभों को साथ ले जाने में सक्षम होना चाहिए और LIMIT 1नीचे दिए गए कार्यों का चयन कैसे संशोधित करके जुड़ने के लिए अतिरिक्त मानदंड लागू करना चाहिए :

CREATE OR REPLACE FUNCTION reduce_joined_testpoly()
RETURNS void
AS $$
DECLARE
  joined_row joined_testpoly%ROWTYPE;
BEGIN
  LOOP
     SELECT array_cat(a.ids, b.ids), st_union(a.geom, b.geom)
         INTO joined_row 
     FROM joined_testpoly a INNER JOIN joined_testpoly b
           on a.ids != b.ids
              and ST_Touches(a.geom, b.geom) and a.geom && b.geom 
              and ST_Relate(a.geom, b.geom)='FF2F11212'
         LIMIT 1;
     IF NOT FOUND THEN
           EXIT;
     END IF;
     INSERT INTO joined_testpoly VALUES (joined_row.ids, joined_row.geom);
     DELETE FROM joined_testpoly
         WHERE joined_testpoly.ids <@ joined_row.ids 
           AND joined_testpoly.ids != joined_row.ids;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE plpgsql;

बात चलाओ:

SELECT reduce_joined_testpoly();

उचित यूनियनें, कोई मल्टीप्लगॉन नहीं:

SELECT ids, st_geometrytype(geom), st_area(geom), st_numgeometries(geom) 
FROM joined_testpoly;
    ids    | st_geometrytype | st_area | st_numgeometries 
-----------+-----------------+---------+------------------
 {5}       | ST_Polygon      |     200 |                1
 {1,2,3,4} | ST_Polygon      |     800 |                1

2

यहाँ संदर्भ के लिए एक और (काम नहीं) रणनीति है (जो कि मैं एक स्पर्श बिंदु मामले को बाहर करने के लिए नहीं मिल सकता है)। यह मेरे अन्य उत्तर से तेज होना चाहिए क्योंकि यह केवल 'एक पास' लेता है।

SELECT st_numgeometries(g), (SELECT st_union(x.geom) FROM st_dump(g) x GROUP BY g)
FROM (
    SELECT unnest(st_clusterintersecting(geom)) g, id < 100 as other_arbitrary_grouping 
    FROM testpoly
    GROUP BY other_arbitrary_grouping) c;

(यदि कोई आईडी = 5 ज्योमेट्री अपने समूह में प्राप्त कर सकता है तो किसी अन्य उत्तर में संशोधन और पोस्ट करने के लिए स्वतंत्र महसूस करें)

पीठ के आईडी आदि आप उपयोग करना चाहते हैं सूची प्राप्त करने के st_containstestpoly तालिका निम्नलिखित जवाब में विस्तृत रूप में पुन: शामिल: /programming//a/37486732/6691 लेकिन मुझे नहीं लगता है कि काम करने के लिए मिल सकता है किसी कारण से बहुभुज के लिए।


2

यहाँ अपनी मूल क्वेरी का उपयोग करके एक त्वरित स्टैब को थोड़ा समायोजित किया गया है:

with gr as (SELECT 
    gid, adj_gid,
    st_AStext(st_union(l2.g1,l2.g2)) AS geo_combo
from (
    --level 2
    SELECT
      t1.id AS gid,
      t1.geom AS g1,
      t2.id AS adj_gid,
      t2.geom AS g2
     from
      testpoly  t1,
      testpoly  t2
     where
      ST_Touches( t1.geom, t2.geom ) 
      AND ST_Relate(t1.geom,t2.geom, '****1****')
      AND t1.geom && t2.geom 
) 
l2) select ST_AsText(st_union(gr.geo_combo)) from gr;

संदर्भ: https://postgis.net/docs/use_postgis_dbmanagement.html#DE-9IM

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