PostGIS में नॉन-नॉटेड चौराहे की समस्या को कैसे ठीक करें?


38

मैं एक PL/Rफ़ंक्शन का उपयोग कर रहा हूं और PostGISअंकों के एक सेट के आसपास वोरोनोई पॉलीगॉन उत्पन्न करने के लिए। जो फ़ंक्शन मैं उपयोग कर रहा हूं वह यहां परिभाषित है । जब मैं किसी विशेष डेटासेट पर इस फ़ंक्शन का उपयोग करता हूं तो मुझे निम्न त्रुटि संदेश मिलता है:

Error : ERROR:  R interpreter expression evaluation error
DETAIL:  Error in pg.spi.exec(sprintf("SELECT %3$s AS id,   
st_intersection('SRID='||st_srid(%2$s)||';%4$s'::text,'%5$s') 
AS polygon FROM %1$s WHERE st_intersects(%2$s::text,'SRID='||st_srid(%2$s)||';%4$s');",  
:error in SQL statement : Error performing intersection: TopologyException: found non-noded 
intersection between LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 
264611, 594406 286813) at 568465.05533706467 264610.82749605528
CONTEXT:  In R support function pg.spi.exec In PL/R function r_voronoi

त्रुटि संदेश के इस भाग की जांच करने से:

Error performing intersection: TopologyException: found non-noded intersection between
LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 264611, 594406 286813) 
at 568465.05533706467 264610.82749605528

यह समस्या ऊपर दी गई समस्या की तरह दिखती है:

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

मैंने शुरू में सोचा था कि यह संदेश समान बिंदुओं के अस्तित्व के कारण हो सकता है, और इस st_translate()फ़ंक्शन को निम्न तरीके से उपयोग करके हल करने का प्रयास किया गया है:

ST_Translate(geom, random()*20, random()*20) as geom 

यह समस्या को ठीक करता है, लेकिन मेरी चिंता यह है कि मैं अब x / y दिशा में ~ 20m तक सभी बिंदुओं का अनुवाद कर रहा हूं। मैं यह भी नहीं बता सकता कि उचित अनुवाद राशि की क्या आवश्यकता है। उदाहरण के लिए, परीक्षण और त्रुटि के माध्यम से इस डेटासेट में यह 20m * random numberठीक है, लेकिन मैं कैसे बता सकता हूं कि यह बड़ा होना चाहिए?

ऊपर की छवि के आधार पर मुझे लगता है कि समस्या यह है कि बिंदु रेखा के साथ प्रतिच्छेद कर रहा है जबकि एल्गोरिथ्म बहुभुज के साथ बिंदु को प्रतिच्छेद करने का प्रयास कर रहा है। मुझे यकीन नहीं है कि मुझे यह सुनिश्चित करने के लिए क्या करना चाहिए कि बिंदु एक बहुभुज के भीतर है, बल्कि एक पंक्ति के साथ प्रतिच्छेद करने के बजाय। इस लाइन पर त्रुटि हो रही है:

"SELECT 
  %3$s AS id, 
  st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'') AS polygon 
FROM 
  %1$s 
WHERE 
  st_intersects(%2$s::text,''SRID=''||st_srid(%2$s)||'';%4$s'');"

मैंने इस पिछले प्रश्न के माध्यम से पढ़ा है, "गैर-एनस्टेड चौराहा" क्या है? इस समस्या को बेहतर ढंग से समझने की कोशिश करें, और इसे हल करने के लिए सबसे अच्छी सलाह दें।


यदि आपके इनपुट शुरू करने के लिए मान्य नहीं हैं, तो उन पर ST_MakeValid () चलाएं। यदि वे वैध हैं, तो एंट्रॉपी जोड़ते हुए, जैसा कि आप कर रहे हैं, अगली ट्रिक उपलब्ध है, और शायद अब के लिए अंतिम चाल है।
पॉल रैमसे

हां, मैं WHERE ST_IsValid(p.geom)शुरू में बिंदुओं को फ़िल्टर करने के लिए उपयोग कर रहा हूं ।
djq

जवाबों:


30

मेरे अनुभव में यह समस्या लगभग हमेशा से होती है:

  1. आपके निर्देशांक (43.231499999999996) में उच्च परिशुद्धता के साथ संयुक्त
  2. पंक्तियाँ जो लगभग संयोग हैं लेकिन समान नहीं हैं

ST_Bufferसमाधानों का "नग्न" दृष्टिकोण आपको # 2 से दूर होने देता है, लेकिन आप इन अंतर्निहित कारणों को हल करने के लिए कुछ भी कर सकते हैं, जैसे कि आपकी ज्यामिति को 1e-6 ग्रिड में तड़कना, आपके जीवन को आसान बना देगा। बफर ज्यामिति आम तौर पर ओवरलैप क्षेत्र की तरह मध्यवर्ती गणना के लिए ठीक हैं, लेकिन आप उन्हें बनाए रखने के बारे में सावधान रहना चाहते हैं क्योंकि वे लंबी दौड़ में आपकी करीब-लेकिन-नहीं-काफी समस्याओं को बदतर बना सकते हैं।

PostgreSQL की अपवाद-हैंडलिंग क्षमता आपको इन विशेष मामलों को संभालने के लिए रैपर फ़ंक्शन लिखने देती है, केवल आवश्यकता होने पर बफरिंग करती है। यहाँ के लिए एक उदाहरण है ST_Intersection; मैं एक समान फ़ंक्शन का उपयोग करता हूं ST_Difference। आपको यह तय करने की आवश्यकता होगी कि आपकी स्थिति में खाली बहुभुज का बफरिंग और संभावित रिटर्न स्वीकार्य है या नहीं।

CREATE OR REPLACE FUNCTION safe_isect(geom_a geometry, geom_b geometry)
RETURNS geometry AS
$$
BEGIN
    RETURN ST_Intersection(geom_a, geom_b);
    EXCEPTION
        WHEN OTHERS THEN
            BEGIN
                RETURN ST_Intersection(ST_Buffer(geom_a, 0.0000001), ST_Buffer(geom_b, 0.0000001));
                EXCEPTION
                    WHEN OTHERS THEN
                        RETURN ST_GeomFromText('POLYGON EMPTY');
    END;
END
$$
LANGUAGE 'plpgsql' STABLE STRICT;

इस दृष्टिकोण के साथ एक और लाभ यह है कि आप उन ज्यामितियों को इंगित कर सकते हैं जो वास्तव में आपकी समस्याओं का कारण बन रही हैं; ब्लॉक RAISE NOTICEमें कुछ बयानों EXCEPTIONको डब्ल्यूकेटी या कुछ और आउटपुट में जोड़ने से आपको समस्या को ट्रैक करने में मदद मिलेगी।


यह एक चतुर विचार है। मैंने अक्सर पाया है कि चौराहे के मुद्दे यूनियनों से आते हैं जो यूनियनों, मतभेदों, बफ़र्स, आदि के संयोजन के दौरान दिखाई देते हैं, जो सब कुछ बफर करके तय किया जा सकता है, या सब कुछ डंप कर सकता है और केवल पॉलीगन्स / म्यूटिप्लिओलगन्स का चयन कर सकता है। यह एक दिलचस्प दृष्टिकोण है।
जॉन पॉवेल

आप ज्यामिति को 1e-6 ग्रिड में तड़कने का उल्लेख करते हैं, लेकिन मैं यहाँ सोच रहा हूँ कि यदि 2 की शक्ति के लिए तड़कना बेहतर होगा। PostGIS (और GEOS) फ्लोटिंग पॉइंट नंबरों का उपयोग करते हैं, इसलिए 10 की शक्ति के लिए तड़कना वास्तव में निर्देशांक को बहुत कम नहीं कर सकता है क्योंकि संख्या में एक परिमित लंबाई बाइनरी प्रतिनिधित्व नहीं हो सकता है। लेकिन अगर आप 2 ^ -16 कहने के लिए स्नैप करते हैं, तो मेरा मानना ​​है कि किसी भी आंशिक भाग को केवल 2 बाइट्स में विभाजित करने की गारंटी होगी। या मैं गलत सोच रहा हूँ?
jpmc26

12

बहुत सारे परीक्षण और त्रुटि के माध्यम से मुझे अंततः एहसास हुआ कि non-noded intersectionएक आत्म-प्रतिच्छेदन समस्या के परिणामस्वरूप। मुझे एक धागा मिला जिसका उपयोग करके सुझाव दिया गया था कि ST_buffer(geom, 0)समस्या को ठीक करने के लिए उपयोग किया जा सकता है (हालांकि यह इसे बहुत धीमा बनाता है)। मैंने तब उपयोग करने की कोशिश की ST_MakeValid()और जब किसी अन्य फ़ंक्शन से पहले सीधे ज्यामिति पर लागू किया गया। यह समस्या को मजबूती से ठीक करता है।

ipoint <- pg.spi.exec(
        sprintf(
            "SELECT 
                    %3$s AS id, 
                    st_intersection(ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''::text), ST_MakeValid(''%5$s'', 0)) AS polygon 
            FROM %1$s 
            WHERE 
                ST_Intersects(ST_MakeValid(%2$s::text),ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''));",
            arg1,
            arg2,
            arg3,
            curpoly,
            buffer_set$ewkb[1]
        )
    )

मैंने इसे उत्तर के रूप में चिह्नित किया है क्योंकि यह एकमात्र तरीका प्रतीत होता है जो मेरी समस्या को ठीक करता है।


11

मैं इसी समस्या में भाग गया (पोस्टग्रैज 9.1.4, पोस्टजीस 2.1.1), और मेरे लिए काम करने वाली एकमात्र चीज ज्यामिति को बहुत छोटे बफर के साथ लपेटना था।

SELECT ST_Intersection(
    (SELECT geom FROM table1), ST_Union(ST_Buffer(geom, 0.0000001))
) FROM table2

ST_MakeValidमेरे लिए काम नहीं किया, और न ही का संयोजन ST_Nodeऔर ST_Dump। बफर के प्रदर्शन में कोई गिरावट नहीं आई, लेकिन अगर मैंने इसे छोटा किया तो मुझे अभी भी एक गैर-एनस्टेड चौराहा त्रुटि प्राप्त हुई।

बदसूरत, लेकिन यह काम करता है।

अद्यतन करें:

ST_Buffer रणनीति अच्छी तरह से काम करने लगती है, लेकिन मैं एक ऐसे मुद्दे पर भाग गया, जहाँ इसने ज्यामिति को भूगोल में डालते समय त्रुटियों का उत्पादन किया। उदाहरण के लिए, यदि एक बिंदु मूल रूप से -90.0 पर है, और यह 0.0000001 से बफर हो गया है, तो यह अब -90.0000001 पर है, जो कि एक अवैध भूगोल है।

इसका मतलब यह था कि भले ही , कई सुविधाओं के लिए वापस आ ST_IsValid(geom)गया था ।tST_Area(geom::geography)NaN

नॉन-नेस्टेड चौराहे की समस्या से बचने के लिए, वैध भूगोल को बनाए रखते हुए, मैंने इस ST_SnapToGridतरह का उपयोग करना समाप्त कर दिया

SELECT ST_Union(ST_MakeValid(ST_SnapToGrid(geom, 0.0001))) AS geom, common_id
    FROM table
    GROUP BY common_id;

6

PostGIS में ST_Node चौराहों पर लाइनों की एक श्रृंखला तोड़ना चाहिए, जो चौराहे समस्या गैर noded का समाधान करना चाहिए। ST_Dump में इसे लपेटने से टूटी हुई लाइनों का कंपोजिट एरे उत्पन्न होता है।

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


यह एक शानदार प्रस्तुति है (धन्यवाद @PaulRamsey)। मैं उपयोग कैसे करना चाहिए ST_Nodeऔर ST_Dump? मुझे लगता है मैं उन्हें समारोह के इस भाग के पास का उपयोग करने की आवश्यकता होगी, लेकिन कुछ नहीं कर रहा हूँ: st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'')में
djq

हम्मम मैंने ध्यान नहीं दिया कि दो लाइनों में एक समान समन्वय था, जो ठीक होना चाहिए। यदि आप प्लॉट करते हैं, तो चौराहे के बिंदु लगभग 18 सेमी चौराहे से दूर हैं। वास्तव में समाधान नहीं, सिर्फ अवलोकन।
वुल्फड्रैड

पूरी तरह से स्पष्ट नहीं है कि मैं st_nodeयहां कैसे उपयोग करूं - क्या मैं इसे पहले इस्तेमाल कर सकता हूं st_intersection?
djq

1
प्रस्तुति अब उपलब्ध नहीं है। जब मैं ST_Clip (रैस्ट, बहुभुज) की कोशिश कर रहा हूं, तो मैं उसी समस्या से घिरा हुआ हूं
जैकी

1
@ जैकी: मैंने उत्तर में प्रस्तुति का लिंक तय किया: पोस्टजीस: पावर यूजर्स के लिए टिप्स
पीट

1

मेरे अनुभव में, मैंने St_SnapToGrid फ़ंक्शन non-noded intersectionका उपयोग करके अपनी त्रुटि को हल किया, जिसने बहुभुज के शीर्ष के निर्देशांक में एक उच्च परिशुद्धता होने की समस्या को हल किया।

SELECT dissolve.machine, dissolve.geom FROM (
        SELECT machine, (ST_Dump(ST_Union(ST_MakeValid(ST_SnapToGrid(geom,0.000001))))).geom 
        FROM cutover_automatique
        GROUP BY machine) as dissolve
WHERE ST_isvalid(dissolve.geom)='t' AND ST_GeometryType(dissolve.geom) = 'ST_Polygon';
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.