PostGIS में बहुभुज सुविधाओं के बीच अंतर की कल्पना करने के लिए लाइनें कैसे बनाएं?


15

मैं polygon_bकुछ बहुभुज सुविधाओं के साथ एक PostGIS तालिका है। एक तालिका भी है polygon_aजिसमें समान बहुभुज होते हैं polygon_bलेकिन मामूली बदलाव के साथ। अब मैं बहुभुज सुविधाओं के बीच अंतर की कल्पना करने के लिए लाइनें बनाना चाहता हूं।

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

मुझे लगता है कि ST_ExteriorRingऔर ST_Differenceकाम करेंगे, लेकिन जहां क्लॉज काफी पेचीदा लगता है।

CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, yourSRID) AS geom
FROM 
    (SELECT
    (ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
    FROM polygon_a, polygon_b
    WHERE 
    -- ?
    ) AS g;

क्या कोई मेरी मदद कर सकता है?

EDIT 1

जैसा कि मैंने 'झुकाव' द्वारा पोस्ट किया है, ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)लेकिन परिणाम उम्मीद के मुताबिक नहीं है।

CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, your_SRID) AS geom
FROM 
    (SELECT
    (ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
    FROM polygon_a, polygon_b
    WHERE 
    ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom))
     AS g;

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

EDIT 2

वर्कअप लोड.com/file/J0WBvRBb (उदाहरण डाटासेट)


मैंने ST_Difference का उपयोग करने से पहले बहुभुजों को बहुखंडों में बदलने की कोशिश की है, लेकिन परिणाम अभी भी अजीब हैं।

CREATE VIEW multiline_a AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_a.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_a;

CREATE VIEW multiline_b AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_b.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_b;

CREATE VIEW line_difference AS SELECT
row_number() over() as gid,
g.geom
FROM
    (SELECT
    (ST_Dump(COALESCE(ST_Difference(multiline_a.geom, multiline_b.geom)))).geom::geometry(linestring, 4326) AS geom
    FROM
    multiline_a, multiline_b)
As g;

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


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

दिलचस्प है, क्या आपके पास डाउनलोड के लिए एक उदाहरण डेटासेट है?
हक्फिन

जवाबों:


10

यहां कुछ नई तरकीबें बताई गई हैं, जिनका उपयोग कर रहे हैं:

  • EXCEPTया तो तालिका से ज्यामितीय हटाने के लिए, इसलिए हम केवल ज्यामितीय पर ध्यान केंद्रित कर सकते हैं जो प्रत्येक तालिका ( A_onlyऔर B_only) के लिए अद्वितीय हैं ।
  • ST_Snap ओवरले ऑपरेटरों के लिए सटीक नोडिंग प्राप्त करने के लिए।
  • मतभेद दिखाने के लिए दो ज्यामिति सेट के बीच सममित अंतरST_SymDifference खोजने के लिए ओवरले ऑपरेटर का उपयोग करें । अद्यतन : इस उदाहरण के लिए समान परिणाम दिखाता है। आप यह देखने के लिए या तो कार्य करने का प्रयास कर सकते हैं।ST_Difference

यह वही होना चाहिए जो आप उम्मीद करते हैं:

-- CREATE OR REPLACE VIEW polygon_SymDifference AS
SELECT row_number() OVER () rn, *
FROM (
  SELECT (ST_Dump(ST_SymDifference(ST_Snap(A, B, tol), ST_Snap(B, A, tol)))).*
  FROM (
    SELECT ST_Union(DISTINCT A_only.geom) A, ST_Union(DISTINCT B_only.geom) B, 1e-5 tol
    FROM (
      SELECT ST_Boundary(geom) geom FROM polygon_a
      EXCEPT SELECT ST_Boundary(geom) geom FROM polygon_b
    ) A_only,
    (
      SELECT ST_Boundary(geom) geom FROM polygon_b
      EXCEPT SELECT ST_Boundary(geom) geom FROM polygon_a
    ) B_only
  ) s
) s;

 rn |                                        geom
----+-------------------------------------------------------------------------------------
  1 | LINESTRING(206.234028204842 -92.0360704110685,219.846021625456 -92.5340701703592)
  2 | LINESTRING(18.556700448873 -36.4496098325257,44.44438533894 -40.5104231486146)
  3 | LINESTRING(-131.974995802602 -38.6145334122719,-114.067738329597 -39.0215165366584)
(3 rows)

तीन लाइनें


इस उत्तर को थोड़ा और अनपैक करने के लिए ST_Boundary, केवल बाहरी के बजाय प्रत्येक बहुभुज की सीमा के साथ पहला कदम मिलता है। उदाहरण के लिए, यदि छेद होते हैं, तो यह सीमा से पता लगाया जाएगा।

EXCEPTखंड एक से geometries कि बी का हिस्सा हैं दूर करने के लिए प्रयोग किया जाता है, और बी से होने वाली पंक्तियां ए का हिस्सा हैं यह पंक्तियों को केवल एक का हिस्सा हैं की संख्या, और बी का हिस्सा केवल कम करता है। जैसे, A_only पाने के लिए:

SELECT ST_Boundary(geom) geom FROM polygon_a
EXCEPT SELECT ST_Boundary(geom) geom FROM polygon_b

यहाँ A_only की 6 पंक्तियाँ हैं, और B_only की 3 पंक्तियाँ: A_only B_only

अगला, ST_Union(DISTINCT A_only.geom)लाइनवर्क को एक एकल ज्यामिति में संयोजित करने के लिए उपयोग किया जाता है, आमतौर पर एक मल्टीलाइनरिंग।

ST_Snap का उपयोग नोड्स को एक ज्यामिति से दूसरे में स्नैप करने के लिए किया जाता है। उदाहरण के लिए ST_Snap(A, B, tol), ए ज्यामिति ले जाएगा, और बी ज्यामिति से अधिक नोड्स जोड़ देगा, या उन्हें बी ज्यामिति में ले जाएगा, अगर वे tolदूरी के भीतर हैं । इन कार्यों का उपयोग करने के कई तरीके हैं, लेकिन विचार प्रत्येक ज्यामिति से निर्देशांक प्राप्त करना है जो एक दूसरे के लिए सटीक हैं। तो तड़क के बाद दो ज्यामितीय इस तरह दिखते हैं:

एक तड़क B तड़क

और अंतर दिखाने के लिए, आप ST_SymDifferenceया तो उपयोग करना चुन सकते हैं या ST_Difference। वे दोनों इस उदाहरण के लिए समान परिणाम दिखाते हैं।


अच्छा उत्तर। मुझे आश्चर्य हुआ कि आपने अपने मध्यस्थ प्रश्नों के परिणामों की कल्पना क्या की थी। यह तुरंत क्यूगिस की तरह नहीं दिखता था, और मैं शायद यह कुछ ऐसा है जो थोड़ी तेजी से प्रस्तुत करता है?
रॉपरमैप्स

1
मैं ज्यामिति को देखने और संसाधित करने के लिए जेटीएस टेस्टबिल्डर का उपयोग करता हूं। यह GEOS और Shapely से संबंधित ज्यामिति इंजन है, लेकिन इसमें जावा-आधारित GUI है।
माइक टी।

क्या लिनेस्‍ट्रिंग के मुद्दों के बीच 'नॉन-नॉटेड चौराहे को अनदेखा / छोड़ना एक तरीका है? सभी इनपुट बहुभुज ठीक प्रतीत होते हैं (QGIS ज्यामिति परीक्षक के साथ जाँच की गई)।
ग्रहण

1
'ST_Boundary (geom) के बजाय' ST_Boundary (ST_SnapToGrid (geom, 0.001)) समस्या हल करती है।
eclipsed_by_the_moon

6

मुझे लगता है कि यह थोड़ा मुश्किल है, क्योंकि आपके दोनों बहुभुजों के अलग-अलग नोड सेट (हरे बहुभुज A, लाल बहुभुज B के अलग-अलग खंड) हैं। दोनों बहुभुजों के खंडों की तुलना करने से एक संकेत मिलता है कि बहुभुज B के किस खंड को संशोधित किया जाएगा।

नोड्स बहुभुज ए

पॉली ए

"अलग" खंडों के नोड्स बहुभुज बी

अलग सीजी

दुर्भाग्य से यह केवल खंड संरचना में अंतर दिखाता है, लेकिन मुझे आशा है कि यह एक प्रारंभिक बिंदु है और यह इस तरह काम करता है:

एक डाउनलोड और अनजिप प्रक्रिया के बाद मैंने कमांड के साथ डेबियन लिनक्स जेसी के तहत PostgrSQL 9.46, PostGIS 2.1 का उपयोग करके डेटा सेट आयात किया है।

$ createdb gis-se
$ psql gis-se < /usr/share/postgis-2.1/postgis.sql
$ psql gis-se < /usr/share/postgis-2.1/spatial_ref_sys.sql
$ shp2pgsql -S polygon_a | psql gis-se
$ shp2pgsql -S polygon_b | psql gis-se

यह मानते हुए कि बहुभुज A के खंड B और इसके विपरीत में नहीं हैं, मैं दोनों बहुभुज सेटों के खंडों के बीच अंतर बनाने की कोशिश करता हूं, प्रत्येक समूह (A या B) में बहुभुज को खंड सदस्यता की उपेक्षा करता है। कई कारणों से मैंने कई दृश्यों में SQL सामान तैयार किया है।

इस जीआईएस-एसई पोस्ट के अनुरूप , मैं दोनों बहुभुजों को खंड तालिकाओं में विघटित करता हूं segments_aऔरsegments_b

-- Segments of the polygon A
CREATE VIEW segments_a AS SELECT sp, ep
FROM
   -- extract the endpoints for every 2-point line segment for each linestring
   (SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep
    FROM
    -- extract the individual linestrings
     (SELECT (ST_Dump(ST_Boundary(geom))).geom
      FROM polygon_a
     ) AS linestrings
    -- be sure that nothing is scrambled
    ORDER BY sp, ep
) AS segments;

खंड तालिका बहुभुज A:

SELECT 
  st_astext(sp) AS sp, 
  st_astext(ep) AS ep 
FROM segments_a 
LIMIT 3;
                    sp                     |                 ep
-------------------------------------------+--------------------------------------------
POINT(-292.268907321861 95.0342877387557)  | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195)  | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.03428773875

उसी प्रक्रिया को बहुभुज बी पर लागू किया गया था।

-- Segments of the polygon B
CREATE VIEW segments_b AS SELECT sp, ep
FROM
   -- extract the endpoints for every 2-point line segment for each linestring
   (SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep
    FROM
    -- extract the individual linestrings
     (SELECT (ST_Dump(ST_Boundary(geom))).geom
      FROM polygon_b
     ) AS linestrings
    -- be sure that nothing is scrambled
    ORDER BY sp, ep
) AS segments;

खंड तालिका बहुभुज बी

SELECT
  st_astext(sp) AS sp, 
  st_astext(ep) AS ep 
FROM segments_b 
LIMIT 3;
                    sp                     |                    ep
-------------------------------------------+-------------------------------------------
POINT(-292.268907321861 95.0342877387557)  | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195)  | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.0342877387557)
...                        

मैं नाम का एक अंतर तालिका दृश्य बना सकता हूं segments_diff_{a,b}। अंतर ए और बी के सेगमेंट सेट में सॉर्ट किए गए प्रारंभ या समाप्ति बिंदुओं की गैर-मौजूदगी द्वारा दिया जाता है।

CREATE VIEW segments_diff_a AS
SELECT st_makeline(b.sp, b.ep) as geom
FROM segments_b as b
LEFT JOIN segments_a as a ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon A
WHERE a.sp IS NULL;

segs diff b

और पूरक सामान:

CREATE VIEW segments_diff_b AS
SELECT st_makeline(a.sp, a.ep) as geom
FROM segments_a as a
LEFT JOIN segments_b as b ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon B
WHERE b.sp IS NULL;

segs अलग है

निष्कर्ष: लाल तीर के साथ चिह्नित छोटे छोटे खंडों के लिए एक उचित परिणाम प्राप्त करने के लिए, दोनों बहुभुजों में एक ही नोड स्ट्रॉकचर और एक नोड स्तर पर एक चौराहे कदम होना चाहिए (बी में बहुभुज ए के शीर्षों को सम्मिलित करना) आवश्यक है। इसके द्वारा किया जा सकता है:

CREATE VIEW segments_bi AS 
SELECT distinct sp, ep
FROM (
 SELECT
      ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
      ST_PointN(geom, generate_series(2, ST_NPoints(geom)  )) as ep
 FROM (
   SELECT st_difference(b.seg, a.seg) as geom FROM 
      segments_diff_a as a, segments_diff_b as b 
      WHERE st_intersects(a.seg, b.seg)
    ) as cut
  ) as segments
  WHERE sp IS NOT NULL AND ep IS NOT NULL
ORDER BY sp, ep;

लेकिन अजीब परिणामों के साथ ...

कटौती संस्करण


आपके प्रयासों के लिए धन्यवाद। खैर, परिणाम अजीब हैं। मुझे आश्चर्य है कि अगर ST_HausdorffDistance () सवाल का जवाब देने में मदद कर सकता है: gis.stackexchange.com/questions/180593/…
चंद्र सागर

हम्म, st_haudorffdistance आपको एक समानता मापता है न कि वांछित सेगमेंट (लाल तीर की ओर इशारा करते हुए)।
हक्फिन

यह सिर्फ एक विचार है, दोनों तालिकाओं की ज्यामिति की तुलना करने के लिए ST_HausdorffDistance का उपयोग किया जा सकता है। बहुभुज स्थानिक रूप से समान नहीं हैं जो मैंने लाइनें बनाने के लिए किए हैं। मुझे नहीं पता कि यह कैसे करना है।
चंद्र सागर

यह सटीक और टोपोलॉजी ( gis.stackexchange.com/a/182838/26213 और webhelp.esri.com/arcgisdesktop/9.2// ) पर होने वाली बात लगती है
huckfinn

1

उदाहरण को देखते हुए, परिवर्तन से तात्पर्य है कि नई तालिका से जो सुविधाएँ बदली गई हैं वे हमेशा पुरानी तालिका से अतिव्यापी सुविधाएँ होंगी। इसलिए आप के साथ किया जाएगा

ST_Overlaps (geoma, geomb) और! ST_Touches (geoma, geomb)

स्पर्शों पर नकारात्मकता इसलिए है क्योंकि सुविधाएँ भी ओवरलैप होती हैं यदि केवल उनकी सीमाएं एक ही वर्टिकल स्थानों को साझा करती हैं।

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