बहुभुज की औसत चौड़ाई की गणना? [बन्द है]


40

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

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

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

मैं एक ऐसे समाधान में रुचि रखता हूं जो आर्कगिस 10, पोस्टगिस 2.0 या क्यूजीआईएस सॉफ्टवेयर का उपयोग करता है। मैंने इस प्रश्न को देखा है और आर्क पैरीज़ 10 के लिए डैन पैटरसन के टूल को डाउनलोड किया है, लेकिन मैं इसके साथ क्या चाहता हूं इसकी गणना करने में सक्षम नहीं था।

मैंने अभी आर्कगिस 10 में न्यूनतम बाउंडिंग ज्योमेट्री टूल की खोज की है जो मुझे निम्नलिखित ग्रीन बहुभुजों का उत्पादन करने में सक्षम बनाता है:

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

यह उन सड़कों के लिए एक अच्छा समाधान की तरह लगता है जो ग्रिड का पालन करते हैं, लेकिन अन्यथा काम नहीं करेंगे, इसलिए मैं अभी भी किसी अन्य सुझाव में दिलचस्पी रखता हूं।


क्या आपने साइडबार पर संभावित समाधानों का उल्लेख किया है? यानी gis.stackexchange.com/questions/2880/… जाहिरा तौर पर एक संभावित डुप्लिकेट पोस्ट के लिए एक तुच्छ उत्तर के रूप में चिह्नित किया गया

@DanPatterson मैंने ऐसा कोई प्रश्न नहीं देखा (कई संबंधित हैं, निश्चित रूप से)। क्या आपका मतलब यह था कि मेरे प्रश्न को चिह्नित किया गया था? मुझे आपकी दूसरी पंक्ति समझ में नहीं आई।
djq

उस संबंधित प्रश्न, @ डान को "चौड़ाई" की एक अलग व्याख्या की चिंता है (ठीक है, वास्तव में, व्याख्या पूरी तरह से स्पष्ट नहीं है)। एक औसत चौड़ाई के बजाय व्यापक बिंदु पर चौड़ाई खोजने पर ध्यान केंद्रित करने के लिए उत्तर दिखाई देते हैं ।
whuber

@Whuber यहाँ केंद्रीकृत करने के लिए चाहते हैं के रूप में विचार विमर्श, एक और सवाल को बंद करने, मेरा सुझाव है कि सवाल लोगों के लिए संपादित किया जाता है समझ " एक आयताकार पट्टी की औसत चौड़ाई के estimative "
पीटर क्रूस

@Peter: एक आयताकार पट्टी है सुतरां एक बहुभुज, अधिक सामान्य शीर्षक खड़े चाहिए।
whuber

जवाबों:


40

समस्या का एक हिस्सा "औसत चौड़ाई" की एक उपयुक्त परिभाषा ढूंढना है। कई प्राकृतिक हैं, लेकिन कम से कम थोड़ा अलग होंगे। सादगी के लिए, उन संपत्तियों के आधार पर परिभाषाओं पर विचार करें जो गणना करने में आसान हैं (उदाहरण के लिए, बफ़र्स के औसत दर्जे के अक्ष परिवर्तन या अनुक्रम के आधार पर उन पर शासन करने जा रहे हैं)।

एक उदाहरण के रूप में, विचार करें कि एक निश्चित "चौड़ाई" के साथ बहुभुज का चापलूसी अंतर्ज्ञान एक छोटा बफर है ( चौकोर छोरों के साथ त्रिज्या आर का कहना है) एक लंबे, काफी सीधे पॉलीलाइन (लंबाई एल के बारे में )। हम इसकी चौड़ाई के रूप में 2r = w के बारे में सोचते हैं । इस प्रकार:

  • इसकी परिधि P लगभग 2L + 2w के बराबर है;

  • इसका क्षेत्रफल A , L के बराबर है।

चौड़ाई w और लंबाई L को फिर द्विघात x ^ 2 - (P / 2) x + A की जड़ों के रूप में पुनर्प्राप्त किया जा सकता है; विशेष रूप से, हम अनुमान लगा सकते हैं

  • w = (P - Sqrt (P ^ 2 - 16A)) / 4

जब आप सुनिश्चित करें कि बहुभुज वास्तव में लंबा और पतला है, तो एक और सन्निकटन के रूप में आप 2L + 2w को बराबर 2L में ले सकते हैं, जहां

  • w (crudely) = 2A / P

इस सन्निकटन में सापेक्ष त्रुटि w / L के समानुपाती है: स्किनियर बहुभुज, करीब w / L शून्य है, और बेहतर सन्निकटन हो जाता है।

न केवल यह दृष्टिकोण अत्यंत सरल है (बस परिधि द्वारा क्षेत्र को विभाजित करें और 2 से गुणा करें), दोनों में से कोई भी फार्मूला यह मायने नहीं रखता है कि बहुभुज कैसे उन्मुख है या यह कहां स्थित है (क्योंकि ऐसे यूक्लिडियन गति न तो क्षेत्र को बदलते हैं और न ही परिधि)।

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

  • पी = 2 एल + 2 डब्ल्यू + 2 पाई ट्विस्ट और

  • A = L w + Pi tw ^ 2।

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


धन्यवाद @whuber जो एक बेहतरीन उत्तर है और इसने मुझे इसके बारे में और अधिक स्पष्ट रूप से सोचने में मदद की है।
djq

@whuber: मैं एक पेपर लिख रहा हूं और मुझे आपके द्वारा यहां बताई गई विधि का एक उचित ('अकादमिक') संदर्भ देना होगा। क्या आपके पास ऐसा संदर्भ है? क्या इस उपाय का कोई नाम है? यदि नहीं, तो मैं आपके नाम पर रख सकता हूं! "ह्यूबर की चौड़ाई को मापने" के बारे में क्या?
जुलिएन

@ जुलिएन मेरे पास कोई संदर्भ नहीं है। यह प्रारूप काम कर सकता है: MISC {20279, TITLE = {बहुभुज की औसत चौड़ाई की गणना?}, AUTHOR = {whuber ( gis.stackexchange.com/users/664/whuber )}, HOWPUBLISHED = {GIS}, NOTE = {URL: gis.stackexchange.com/q/20279/664 (संस्करण: 2013-08-13)}, EPRINT = { gis.stackexchange.com/q/20279 }, URL = { gis.stackexchange.com/q/20279 }}
whuber

18

यहां मैं @whuber समाधान के बारे में थोड़ा अनुकूलन दिखाता हूं, और "बफर चौड़ाई" के संदर्भ में डाल रहा हूं, क्योंकि यह एक अधिक सामान्य समस्या के समाधान को एकीकृत करने के लिए उपयोगी है: क्या एक st_buffer उलटा फ़ंक्शन है, जो एक चौड़ाई का अनुमान देता है?

CREATE FUNCTION buffer_width(
        -- rectangular strip mean width estimator
    p_len float,   -- len of the central line of g
    p_geom geometry, -- g
    p_btype varchar DEFAULT 'endcap=flat' -- st_buffer() parameter
) RETURNS float AS $f$
  DECLARE
    w_half float;
    w float;    
  BEGIN
         w_half := 0.25*ST_Area(p_geom)/p_len;
         w      := 0.50*ST_Area( ST_Buffer(p_geom,-w_half,p_btype) )/(p_len-2.0*w_half);
     RETURN w_half+w;
  END
$f$ LANGUAGE plpgsql IMMUTABLE;

इस समस्या के लिए, के बारे में @celenius सवाल सड़क चौड़ाई , sw, समाधान है

 sw = buffer_width(ST_Length(g1), g2)

जहां sw"औसत चौड़ाई" है, g1की केंद्रीय पंक्ति g2और सड़क g2एक POLYGON है । मैंने केवल OGC मानक पुस्तकालय का उपयोग किया, PostGIS के साथ परीक्षण किया , और एक ही बफर_ एक्सपोज़र फ़ंक्शन के साथ अन्य गंभीर व्यावहारिक अनुप्रयोगों को हल किया।

प्रदर्शन

A2का क्षेत्रफल g2, L1केंद्रीय रेखा की लंबाई ( g1) है g2

यह मानते हुए कि हम g2द्वारा उत्पन्न किया जा सकता है g2=ST_Buffer(g1,w), और g1यह एक सीधा है, इसलिए g2लंबन L1और चौड़ाई के साथ एक आयत है 2*w, और

    A2 = L1*(2*w)   -->  w = 0.5*A2/L1

यह @whuber का समान सूत्र नहीं है, क्योंकि यहां wआयत ( g2) चौड़ाई का आधा हिस्सा है । यह एक अच्छा अनुमानक है, लेकिन जैसा कि हम परीक्षण (नीचे) द्वारा देख सकते हैं, सटीक नहीं है, और फ़ंक्शन इसे एक सुराग के रूप में उपयोग करता है, g2क्षेत्र को कम करने के लिए , और अंतिम अनुमानक के रूप में।

यहां हम "एंडकैप = स्क्वायर" या "एंडकैप = राउंड" वाले बफ़र्स का मूल्यांकन नहीं करते हैं, A2 उन्हें उसी के साथ एक बिंदु बफर के एक क्षेत्र की राशि की आवश्यकता होती है w

संदर्भ: 2005 के एक समान फोरम में , डब्ल्यू। ह्यूबर इस तरह के और अन्य समाधान बताते हैं।

TESTS और REASONS

उम्मीद के अनुसार, सीधी रेखा के परिणाम सटीक हैं। लेकिन अन्य ज्यामितीयों के लिए परिणाम निराशाजनक हो सकते हैं। मुख्य कारण, शायद, सभी मॉडल सटीक आयतों के लिए हैं, या ज्यामितीय के लिए जिसे "स्ट्रिप आयत" के रूप में अनुमानित किया जा सकता है। इस सन्निकटन की सीमा की जाँच के लिए एक "परीक्षण किट" ( wfactorऊपर के परिणामों में देखें )।

 SELECT *, round(100.0*(w_estim-w)/w,1) as estim_perc_error
    FROM (
        SELECT btype, round(len,1) AS len, w, round(w/len,3) AS wfactor,
               round(  buffer_width(len, gbase, btype)  ,2) as w_estim ,
               round(  0.5*ST_Area(gbase)/len       ,2) as w_near
        FROM (
         SELECT
            *, st_length(g) AS len, ST_Buffer(g, w, btype) AS gbase
         FROM (
               -- SELECT ST_GeomFromText('LINESTRING(50 50,150 150)') AS g, -- straight
               SELECT ST_GeomFromText('LINESTRING(50 50,150 150,150 50,250 250)') AS g,
            unnest(array[1.0,10.0,20.0,50.0]) AS w
              ) AS t, 
             (SELECT unnest(array['endcap=flat','endcap=flat join=bevel']) AS btype
             ) AS t2
        ) as t3
    ) as t4;

परिणाम:

RECTANGLES के साथ (केंद्रीय लाइन एक चमक लाइन है):

         btype          |  len  |  w   | wfactor | w_estim | w_near | estim_perc_error 
------------------------+-------+------+---------+---------+--------+------------------
 endcap=flat            | 141.4 |  1.0 |   0.007 |       1 |      1 |                0
 endcap=flat join=bevel | 141.4 |  1.0 |   0.007 |       1 |      1 |                0
 endcap=flat            | 141.4 | 10.0 |   0.071 |      10 |     10 |                0
 endcap=flat join=bevel | 141.4 | 10.0 |   0.071 |      10 |     10 |                0
 endcap=flat            | 141.4 | 20.0 |   0.141 |      20 |     20 |                0
 endcap=flat join=bevel | 141.4 | 20.0 |   0.141 |      20 |     20 |                0
 endcap=flat            | 141.4 | 50.0 |   0.354 |      50 |     50 |                0
 endcap=flat join=bevel | 141.4 | 50.0 |   0.354 |      50 |     50 |                0

अन्य GEOMETRIES के साथ (मध्य रेखा मुड़ी हुई):

         btype          | len |  w   | wfactor | w_estim | w_near | estim_perc_error 
 -----------------------+-----+------+---------+---------+--------+------------------
 endcap=flat            | 465 |  1.0 |   0.002 |       1 |      1 |                0
 endcap=flat join=bevel | 465 |  1.0 |   0.002 |       1 |   0.99 |                0
 endcap=flat            | 465 | 10.0 |   0.022 |    9.98 |   9.55 |             -0.2
 endcap=flat join=bevel | 465 | 10.0 |   0.022 |    9.88 |   9.35 |             -1.2
 endcap=flat            | 465 | 20.0 |   0.043 |   19.83 |  18.22 |             -0.9
 endcap=flat join=bevel | 465 | 20.0 |   0.043 |   19.33 |  17.39 |             -3.4
 endcap=flat            | 465 | 50.0 |   0.108 |   46.29 |  40.47 |             -7.4
 endcap=flat join=bevel | 465 | 50.0 |   0.108 |   41.76 |  36.65 |            -16.5

 wfactor= w/len
 w_near = 0.5*area/len
 w_estim is the proposed estimator, the buffer_width function.

के बारे में btypeदेख ST_Buffer गाइड , अच्छा ilustratins और यहां इस्तेमाल किया LineStrings साथ।

निष्कर्ष :

  • का अनुमानक w_estimहमेशा से बेहतर होता है w_near;
  • "आयताकार के पास" g2ज्यामितीय, इसके ठीक, किसी भी के लिएwfactor
  • एक अन्य ज्यामिति के लिए ("आयताकार स्ट्रिप्स के पास"), wfactor=~0.01त्रुटि के 1% के लिए सीमा का उपयोग करें w_estim। इस wfactor तक, किसी अन्य अनुमानक का उपयोग करें।

सावधानी और रोकथाम

अनुमान त्रुटि क्यों होती है? जब आप उपयोग करते हैं ST_Buffer(g,w), तो आप उम्मीद करते हैं, "आयताकार पट्टी मॉडल" द्वारा, कि चौड़ाई के बफर द्वारा जोड़ा गया नया क्षेत्र wलगभग ... w*ST_Length(g)या w*ST_Perimeter(g)नहीं है, आमतौर पर ओवरले द्वारा (मुड़ी हुई लाइनों को देखें) या "स्टाइलिंग" द्वारा, जब है औसत wगलती का अनुमान । यह परीक्षणों का मुख्य संदेश है।

बफर के किसी भी राजा में इस समस्या का पता लगाने के लिए, बफर पीढ़ी के व्यवहार की जाँच करें:

SELECT btype, w, round(100.0*(a1-len1*2.0*w)/a1)::varchar||'%' AS straight_error,  
                 round(100.0*(a2-len2*2.0*w)/a2)::varchar||'%' AS curve2_error,
                 round(100.0*(a3-len3*2.0*w)/a3)::varchar||'%' AS curve3_error
FROM (
 SELECT
    *, st_length(g1) AS len1, ST_Area(ST_Buffer(g1, w, btype)) AS a1,
    st_length(g2) AS len2, ST_Area(ST_Buffer(g2, w, btype)) AS a2,
    st_length(g3) AS len3, ST_Area(ST_Buffer(g3, w, btype)) AS a3
 FROM (
       SELECT ST_GeomFromText('LINESTRING(50 50,150 150)') AS g1, -- straight
              ST_GeomFromText('LINESTRING(50 50,150 150,150 50)') AS g2,
              ST_GeomFromText('LINESTRING(50 50,150 150,150 50,250 250)') AS g3,
              unnest(array[1.0,20.0,50.0]) AS w
      ) AS t, 
     (SELECT unnest(array['endcap=flat','endcap=flat join=bevel']) AS btype
     ) AS t2
) as t3;

परिणाम:

         btype          |  w   | straight_error | curve2_error | curve3_error 
------------------------+------+----------------+--------------+--------------
 endcap=flat            |  1.0 | 0%             | -0%          | -0%
 endcap=flat join=bevel |  1.0 | 0%             | -0%          | -1%
 endcap=flat            | 20.0 | 0%             | -5%          | -10%
 endcap=flat join=bevel | 20.0 | 0%             | -9%          | -15%
 endcap=flat            | 50.0 | 0%             | -14%         | -24%
 endcap=flat join=bevel | 50.0 | 0%             | -26%         | -36%

        चेतावनी


13

यदि आप अपने पॉलीगॉन डेटा को अपने सेंटरलाइन डेटा (स्थानिक या सारणीबद्ध माध्यम से) में शामिल कर सकते हैं, तो प्रत्येक सेंटरलाइन एलाइनमेंट के लिए पॉलीगॉन क्षेत्रों को योग करें और सेंटरलाइन की लंबाई से विभाजित करें।


यह सच है! इस मामले में, मेरी सेंटलाइन्स समान लंबाई नहीं हैं, लेकिन मैं हमेशा उन्हें एक के रूप में शामिल कर सकता हूं, और उन्हें प्रति बहुभुज में विभाजित कर सकता हूं।
djq

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

धन्यवाद Scro, यह अभी PostGIS में नहीं है, लेकिन इसमें लोड करना बहुत जल्दी है। मुझे लगता है कि मैं पहले व्हिबर के दृष्टिकोण की कोशिश करूंगा, लेकिन मैं इसे PostGIS के परिणामों से तुलना करूंगा (और SQL मदद की पेशकश के लिए धन्यवाद, लेकिन मैं प्रबंधन करने में सक्षम होना चाहिए)। मुख्य रूप से पहले मेरे सिर में दृष्टिकोण को स्पष्ट करने की कोशिश की जा रही है।
djq

+1 यह उन परिस्थितियों के लिए एक अच्छा सरल समाधान है जहां यह उपलब्ध है।
whuber

9

मैंने बहुभुज की औसत चौड़ाई के लिए एक सूत्र विकसित किया है और इसे पायथन / आर्कपी फ़ंक्शन में डाला है। मेरे सूत्र से व्युत्पन्न है (लेकिन काफी हद तक फैली हुई है) औसत चौड़ाई की सबसे सीधी धारणा है जो मैंने कहीं और चर्चा की है; वह है, एक वृत्त का व्यास जिसका क्षेत्रफल आपके बहुभुज के समान है। हालांकि, ऊपर दिए गए प्रश्न और मेरी परियोजना में, मुझे सबसे अधिक संकीर्ण अक्ष की चौड़ाई में दिलचस्पी थी। इसके अलावा, मैं संभावित जटिल, गैर-उत्तल आकृतियों के लिए औसत चौड़ाई में दिलचस्पी रखता था।

मेरा समाधान था:

(perimeter / pi) * area / (perimeter**2 / (4*pi))
= 4 * area / perimeter

अर्थात्:

(Diameter of a circle with the same perimeter as the polygon) * Area / (Area of a circle with the same perimeter as the polygon)

समारोह है:

def add_average_width(featureClass, averageWidthField='Width'):
    '''
    (str, [str]) -> str

    Calculate the average width of each feature in the feature class. The width
        is reported in units of the feature class' projected coordinate systems'
        linear unit.

    Returns the name of the field that is populated with the feature widths.
    '''
    import arcpy
    from math import pi

    # Add the width field, if necessary
    fns = [i.name.lower() for i in arcpy.ListFields(featureClass)]
    if averageWidthField.lower() not in fns:
        arcpy.AddField_management(featureClass, averageWidthField, 'DOUBLE')

    fnsCur = ['SHAPE@LENGTH', 'SHAPE@AREA', averageWidthField]
    with arcpy.da.UpdateCursor(featureClass, fnsCur) as cur:
        for row in cur:
            perim, area, width = row
            row[-1] = ((perim/pi) * area) / (perim**2 / (4 * pi))
            cur.updateRow(row)

    return averageWidthField

ऊपर से फ़ंक्शन का उपयोग करके विभिन्न आकारों में औसत चौड़ाई (और संदर्भ के लिए कुछ अन्य ज्यामिति विशेषताएँ) के साथ एक निर्यातित नक्शा है:

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


4
यदि आप अभिव्यक्ति को सरल बनाते हैं, तो यह सिर्फ होगा area / perimeter * 4
culebrón

धन्यवाद, @ culebrón। मैं सूत्र की सरलता पर अवधारणा की स्पष्टता के लिए जा रहा था, और मैंने समीकरण को सरल बनाने के बारे में कभी सोचा भी नहीं था। इससे मुझे कुछ प्रसंस्करण समय बचाना चाहिए।
टॉम

0

अनुमानित औसत दर्जे की धुरी के साथ एक और समाधान:

  1. बहुभुज की अनुमानित औसत दर्जे की धुरी की गणना;
  2. अनुमानित औसत दर्जे की धुरी की लंबाई प्राप्त करें;
  3. बहुभुज की सीमा पर अक्ष के दोनों सिरों से दूरी प्राप्त करें;
  4. सम धुरी की लंबाई और चरण 3 से दूरी - यह लगभग बहुभुज की लंबाई है;
  5. अब आप इस लंबाई से बहुभुज के क्षेत्रफल को विभाजित कर सकते हैं और बहुभुज की औसत चौड़ाई प्राप्त कर सकते हैं।

परिणाम निश्चित रूप से उन बहुभुजों के लिए गलत होगा जहां अनुमानित औसत दर्जे का अक्ष एक निरंतर निरंतर रेखा नहीं है, इसलिए आप चरण 1 से पहले इसे जांच सकते हैं और NULLकुछ या वापस कर सकते हैं।

उदाहरण

यहाँ PostgreSQL समारोह (: यदि आप स्थापित करने की आवश्यकता नोट के उदाहरण है PostGIS और postgis_sfcgal एक्सटेंशन):

CREATE FUNCTION ApproximatePolygonLength(geom geometry)
RETURNS float AS $$
    SELECT
        CASE
            /* in case when approximate medial axis is empty or simple line
             * return axis length
             */
            WHEN (ST_GeometryType(axis.axis) = 'ST_LineString' OR ST_IsEmpty(axis.axis))
                THEN axis_length.axis_length
                    + start_point_distance.start_point_distance
                    + end_point_distance.end_point_distance
            /* else geometry is too complex to define length */
            ELSE NULL
        END AS length
    FROM
        LATERAL (
            SELECT
                ST_MakeValid(geom) AS valid_geom
        ) AS valid_geom,
        LATERAL (
            SELECT
                /* `ST_LineMerge` returns:
                 *  - `GEOMETRYCOLLECTION EMPTY`, if `ST_ApproximateMedialAxis` is an empty line (i.e. for square);
                 *  - `LINESTRING ...`, if `ST_ApproximateMedialAxis` is a simple line;
                 *  - `MULTILINESTRING ...`, if `ST_ApproximateMedialAxis` is a complex line
                 *     that can not be merged to simple line. In this case we should return `NULL`.
                 */
                ST_LineMerge(
                    ST_ApproximateMedialAxis(
                        valid_geom.valid_geom
                    )
                ) AS axis
        ) AS axis,
        LATERAL (
            SELECT
                ST_Boundary(valid_geom.valid_geom) AS border
        ) AS border,
        LATERAL (
            SELECT
                ST_Length(axis.axis) AS axis_length
        ) AS axis_length,
        LATERAL (
            SELECT
                ST_IsClosed(axis.axis) AS axis_is_closed
        ) AS axis_is_closed,
        LATERAL (
            SELECT
                CASE WHEN axis_is_closed.axis_is_closed THEN 0
                ELSE
                    ST_Distance(
                        border.border,
                        CASE ST_GeometryType(axis.axis)
                            WHEN 'ST_LineString' THEN ST_StartPoint(axis.axis)
                            /* if approximate medial axis is empty (i.e. for square),
                             * get centroid of geometry
                             */
                            ELSE ST_Centroid(valid_geom.valid_geom)
                        END
                    )
                END AS start_point_distance
        ) AS start_point_distance,
        LATERAL (
            SELECT
                CASE WHEN axis_is_closed.axis_is_closed THEN 0
                ELSE
                    ST_Distance(
                        border.border,
                        CASE ST_GeometryType(axis.axis)
                            WHEN 'ST_LineString' THEN ST_EndPoint(axis.axis)
                            /* if approximate medial axis is empty (i.e. for square),
                             * get centroid of geometry
                             */
                            ELSE ST_Centroid(valid_geom.valid_geom)
                        END
                    )
                END AS end_point_distance
        ) AS end_point_distance;
$$ LANGUAGE SQL;

CREATE FUNCTION ApproximatePolygonWidth(geom geometry)
RETURNS float AS $$
    SELECT
        CASE
            WHEN length IS NULL THEN NULL
            ELSE area.area / length.length
        END AS width
    FROM
        (
            SELECT ApproximatePolygonLength(geom) AS length
        ) AS length,
        (
            SELECT
                ST_Area(
                    ST_MakeValid(geom)
                ) AS area
        ) AS area;
$$ LANGUAGE SQL;

हानि:

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

उदाहरण:

टूटा हुआ उदाहरण

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