मैं 2d बहुभुज के क्षेत्र की गणना कैसे करूं?


81

2d अंतरिक्ष में अंकों की एक श्रृंखला को मानते हुए, जो आत्म-प्रतिच्छेद नहीं करता है, परिणामी बहुभुज के क्षेत्रफल को निर्धारित करने का एक कुशल तरीका क्या है?

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


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

डिफ एरिया (बहुभुज): एब्स (numpy.cross (पॉलीगॉन, numpy.roll (पॉलीगॉन, -1, 0)))। राशि () / 2)
iouvxz

जवाबों:


111

यहाँ मानक विधि , AFAIK है। मूल रूप से प्रत्येक शीर्ष के चारों ओर क्रॉस उत्पादों का योग। त्रिकोणासन की तुलना में बहुत सरल है।

पायथन कोड, एक बहुभुज को (x, y) शीर्ष निर्देशांक की एक सूची के रूप में प्रस्तुत किया गया है, जो अंतिम शीर्ष से पहली तक चारों ओर घूमता है:

def area(p):
    return 0.5 * abs(sum(x0*y1 - x1*y0
                         for ((x0, y0), (x1, y1)) in segments(p)))

def segments(p):
    return zip(p, p[1:] + [p[0]])

डेविड लेहावी टिप्पणी: यह उल्लेख करने योग्य है कि यह एल्गोरिथ्म क्यों काम करता है: यह कार्यों emy और x के लिए ग्रीन की प्रमेय का अनुप्रयोग है ; ठीक उसी तरह जिस तरह से एक प्लांटरमीटर काम करता है। अधिक विशेष रूप से:

ऊपर का सूत्र =
integral_over_perimeter(-y dx + x dy) =
integral_over_area((-(-dy)/dy+dx/dx) dy dx) =
2 Area


7
यह ध्यान देने योग्य है कि यह एल्गोरिदम क्यों काम करता है: यह कार्यों के लिए ग्रीन के प्रमेय का एक अनुप्रयोग है -y और x; ठीक उसी तरह जिस तरह से एक प्लांटरमीटर काम करता है। अधिक विशेष रूप से: ऊपर का सूत्र = इंटीग्रल_पेरमीयर (-y dx + x डाई) = इंटीग्रल_आर्इया ((- (- डाई) / डाई + डीएक्स / डीएक्स) डाइडीएक्स = २ क्षेत्र
डेविड लेहैन

6
पोस्ट में लिंक मृत है। क्या किसी और के पास है?
याकॉव

1
Compgeom-discuss@research.bell-labs.com मेलिंग लिस्ट पर लिंक की गई चर्चा मेरे लिए अटल है। मैंने Google Cache से संदेश कॉपी किया: gist.github.com/1200393
एंड्रयू Андрей Листочкин

2
@ perfectionm1ng स्विचिंग दिशाएँ राशि में साइन को फ्लिप करती हैं, लेकिन abs()साइन को स्ट्रिप करती हैं।
डेरियस बेकन

3
सीमाएं: यह विधि स्व-प्रतिच्छेदन बहुभुज के लिए गलत उत्तर का उत्पादन करेगी, जहां एक तरफ दूसरे को पार करता है, जैसा कि दाईं ओर दिखाया गया है। यह त्रिकोण, नियमित और अनियमित बहुभुज, उत्तल या अवतल बहुभुज के लिए सही ढंग से काम करेगा। ( mathopenref.com/coordpolygonarea.html )
OneWorld

14

क्रॉस उत्पाद एक क्लासिक है।

यदि आपके पास करने के लिए इस तरह की संगणना है, तो निम्न अनुकूलित संस्करण का प्रयास करें जिसमें आधे से कम गुणन की आवश्यकता हो:

area = 0;
for( i = 0; i < N; i += 2 )
   area += x[i+1]*(y[i+2]-y[i]) + y[i+1]*(x[i]-x[i+2]);
area /= 2;

मैं स्पष्टता के लिए सरणी सबस्क्रिप्ट का उपयोग करता हूं। यह पॉइंटर्स का उपयोग करने के लिए अधिक कुशल है। हालांकि अच्छे कंपाइलर इसे आपके लिए करेंगे।

बहुभुज को "बंद" माना जाता है, जिसका अर्थ है कि आप पहले बिंदु को सबस्क्रिप्ट एन के साथ बिंदु के रूप में कॉपी करते हैं। यह भी मान लेते हैं कि बहुभुज के पास समान अंक हैं। यदि एन भी नहीं है, तो पहले बिंदु की एक अतिरिक्त प्रति संलग्न करें।

एल्गोरिथ्म को क्लासिक क्रॉस उत्पाद एल्गोरिदम के दो क्रमिक पुनरावृत्तियों को अनियंत्रित और संयोजित करके प्राप्त किया जाता है।

मुझे यकीन नहीं है कि दो एल्गोरिदम संख्यात्मक सटीकता के बारे में कैसे तुलना करते हैं। मेरी धारणा यह है कि उपरोक्त एल्गोरिथ्म क्लासिक की तुलना में बेहतर है क्योंकि गुणन घटाव की परिशुद्धता के नुकसान को बहाल करने के लिए करते हैं। जब GPU के रूप में फ़्लोट्स का उपयोग करने के लिए विवश किया जाता है, तो यह एक महत्वपूर्ण अंतर बना सकता है।

संपादित करें: "त्रिकोण और बहुभुज 2 डी और 3 डी का क्षेत्र" एक और भी अधिक कुशल विधि का वर्णन करता है

// "close" polygon
x[N] = x[0];
x[N+1] = x[1];
y[N] = y[0];
y[N+1] = y[1];

// compute area
area = 0;
for( size_t i = 1; i <= N; ++i )
  area += x[i]*( y[i+1] - y[i-1] );
area /= 2;

1
मैं कल्पना नहीं कर सकता कि दूसरा कोड स्निपेट काम करेगा। यह बहुत स्पष्ट है कि, बहुभुज एक्स अक्ष पर है, इसका क्षेत्रफल जितना बड़ा होगा।
साइगॉन

1
यह कुछ गुणाओं को बचाने के ऊपर वर्णित एल्गोरिथ्म का एक सही गणितीय पुनर्व्यवस्था है। आप सही हैं, लेकिन अन्य शीर्षों द्वारा परिभाषित क्षेत्र घट जाएंगे। लेकिन इससे वास्तव में सटीक गिरावट हो सकती है।
चामिक

2
आपने जो अनदेखा किया है वह यह है कि जोड़ घटाव के कारण हमेशा कुछ नकारात्मक शब्द होते हैं। किसी भी 2d बहुभुज आकार पर विचार करें और लगातार शीर्षों के y मूल्यों की तुलना करें। आप देखेंगे कि कुछ घटाव एक नकारात्मक मान और कुछ सकारात्मक निकलेंगे।
चम्मिक

2
वास्तव में, वह आखिरी पैराग्राफ है जो मैं अपने दिमाग को लपेट नहीं सकता! I <= N के साथ यह काम करता है। आपके धैर्य के लिए धन्यवाद, मैं सब कुछ वापस ले लेता हूं :)
साइगॉन

1
साइड नोट पर, एल्गोरिथ्म द्वारा लौटाया गया क्षेत्र "हस्ताक्षरित" (अंकों के क्रम के आधार पर नकारात्मक या सकारात्मक) है, इसलिए यदि आप हमेशा सकारात्मक क्षेत्र चाहते हैं तो निरपेक्ष मूल्य का उपयोग करें।
नाइटलाइफ

11

यह पृष्ठ दिखाता है कि सूत्र

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

सरल किया जा सकता है:

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

यदि आप कुछ शर्तों को लिखते हैं और उन्हें सामान्य कारकों के अनुसार समूहित करते हैं xi, तो समानता देखना मुश्किल नहीं है।

अंतिम सारांश अधिक कुशल है क्योंकि इसके लिए केवल nगुणा की आवश्यकता होती है 2n

def area(x, y):
    return abs(sum(x[i] * (y[i + 1] - y[i - 1]) for i in xrange(-1, len(x) - 1))) / 2.0

मैंने यह सरलीकरण जोए किंग्टन से सीखा, यहाँ


यदि आपके पास NumPy है, तो यह संस्करण तेज़ है (सभी के लिए लेकिन बहुत छोटी सरणियाँ):

def area_np(x, y):        
    x = np.asanyarray(x)
    y = np.asanyarray(y)
    n = len(x)
    shift_up = np.arange(-n+1, 1)
    shift_down = np.arange(-1, n-1)    
    return (x * (y.take(shift_up) - y.take(shift_down))).sum() / 2.0

1
NumPy संस्करण के लिए धन्यवाद।
भौतिकीविद्या

4

किसी भी अन्य बाधाओं के बिना बिंदुओं का एक सेट एक बहुभुज को विशिष्ट रूप से परिभाषित नहीं करता है।

तो, पहले आपको यह तय करना होगा कि इन बिंदुओं से क्या बहुभुज बनाना है - शायद उत्तल पतवार? http://en.wikipedia.org/wiki/Convex_hull

फिर त्रिभुज और गणना क्षेत्र। http://www.mathopenref.com/polygonir अनियमितarea.html


4

त्रिभुज और सम त्रिभुज क्षेत्रों पर विस्तार करने के लिए, वे कार्य यदि आप उत्तल बहुभुज के होते हैं या आप एक ऐसा बिंदु उठाते हैं जो बहुभुज को प्रतिच्छेद करने वाले हर दूसरे बिंदु पर रेखाएँ उत्पन्न नहीं करता है।

एक सामान्य गैर-प्रतिच्छेदन बहुभुज के लिए, आपको वैक्टर के क्रॉस उत्पाद (संदर्भ बिंदु, बिंदु a), (संदर्भ बिंदु, बिंदु b) पर योग करने की आवश्यकता होती है, जहाँ a और b एक दूसरे के लिए "अगले" होते हैं।

मान लें कि आपके पास बहुभुज को परिभाषित करने वाले बिंदुओं की एक सूची है (क्रम में बिंदु i और i + 1 बहुभुज की एक रेखा बनाते हैं):

सम = (i से 1 से n - 1) के लिए क्रॉस उत्पाद ((बिंदु 0, बिंदु i), (बिंदु 0, बिंदु i + 1))।

उस क्रॉस उत्पाद का परिमाण लें और आपके पास सतह क्षेत्र है।

यह एक अच्छा संदर्भ बिंदु चुनने के बारे में चिंता किए बिना अवतल बहुभुज को संभाल लेगा; कोई भी तीन बिंदु जो एक त्रिभुज उत्पन्न करते हैं जो बहुभुज के अंदर नहीं है, एक क्रॉस उत्पाद होगा जो बहुभुज के अंदर किसी भी त्रिभुज के विपरीत दिशा में इंगित करता है, इसलिए क्षेत्रों को सही ढंग से अभिव्यक्त किया जाता है।


3

बहुभुज के क्षेत्र को शांत करने के लिए

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry1#polygon_area

int cross(vct a,vct b,vct c)
{
    vct ab,bc;
    ab=b-a;
    bc=c-b;
    return ab.x*bc.y-ab.y*bc.x;
}    
double area(vct p[],int n)
{ 
    int ar=0;
    for(i=1;i+1<n;i++)
    {
        vct a=p[i]-p[0];
        vct b=p[i+1]-p[0];
        area+=cross(a,b);
    }
    return abs(area/2.0);
}    

यह एक 3 साल पुराना सवाल है जो स्वीकृत उत्तर पर 34 अपवोट के साथ है। हमें बताएं कि आपका उत्तर पहले से पोस्ट किए गए अन्य उत्तरों से बेहतर कैसे है।
मार्क टेलर

3
यह c और python में एक उदाहरण है। नहीं बेहतर लेकिन अच्छा अलग अलग भाषाओं में यह है करने के लिए
underdoeg

2

या एक समोच्च अभिन्न करते हैं। स्टोक्स के प्रमेय आपको समोच्च अभिन्न के रूप में अभिन्न क्षेत्र को व्यक्त करने की अनुमति देता है। थोड़ा गॉस क्वैडचर और बॉब आपके चाचा।


2

भाषा स्वतंत्र समाधान:

GIVEN: एक बहुभुज ALWAYS को n-2 त्रिभुजों द्वारा बनाया जा सकता है जो ओवरलैप नहीं करते हैं (n = अंक या पक्षों की संख्या)। 1 त्रिकोण = 3 पक्षीय बहुभुज = 1 त्रिकोण; 1 वर्ग = 4 पक्षीय बहुभुज = 2 त्रिकोण; आदि विज्ञापन nauseam QED

इसलिए, एक बहुभुज को "काट" त्रिकोणों द्वारा कम किया जा सकता है और कुल क्षेत्रफल इन त्रिकोणों के क्षेत्रों का योग होगा। इसे कागज़ और कैंची के साथ आज़माएं, यदि आप निम्नलिखित प्रक्रिया से पहले इसकी कल्पना कर लें तो सबसे अच्छा है।

यदि आप बहुभुज मार्ग में कोई 3 लगातार अंक लेते हैं और इन बिंदुओं के साथ एक त्रिकोण बनाते हैं, तो आपके पास एक और केवल तीन संभावित विकल्पों में से एक होगा:

  1. परिणामस्वरूप त्रिकोण मूल बहुभुज के अंदर पूरी तरह से है
  2. परिणामस्वरूप त्रिकोण मूल बहुभुज के पूरी तरह से बाहर है
  3. परिणामस्वरूप त्रिभुज मूल बहुभुज में आंशिक रूप से समाहित है

हम केवल उन मामलों में रुचि रखते हैं जो पहले विकल्प में आते हैं (पूरी तरह से निहित)।

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

कैसे इस कार्यक्रम को लागू करने के लिए:

(निरंतर) बिंदुओं की एक सरणी बनाएं, जो बहुभुज AROUND पथ का प्रतिनिधित्व करता है। बिंदु ० पर प्रारंभ करें। बिंदु x, x + १ और x + २ से त्रिभुज (एक समय में एक) बनाते हुए सरणी चलाएँ। प्रत्येक त्रिभुज को एक आकृति से एक क्षेत्र में बदलना और बहुभुज से निर्मित क्षेत्र के साथ इसे काटना। यदि परिणामी चौराहा मूल त्रिकोण के समान है, तो कहा गया त्रिकोण पूरी तरह से बहुभुज में निहित है और इसे काट दिया जा सकता है। सरणी से x + 1 निकालें और x = 0 से फिर से शुरू करें। अन्यथा (यदि त्रिकोण [आंशिक रूप से या पूरी तरह से] बहुभुज के बाहर है), तो सरणी में अगले बिंदु x + 1 पर जाएं।

इसके अलावा यदि आप मैपिंग के साथ एकीकरण करना चाह रहे हैं और जियो पॉइंट्स से शुरू कर रहे हैं, तो आपको जियो पॉइंट्स से स्क्रीनप्ले FIRST में बदलना होगा। इसके लिए पृथ्वी के आकार के लिए एक मॉडलिंग और सूत्र तय करने की आवश्यकता होती है (हालांकि हम पृथ्वी को एक गोले के रूप में सोचते हैं, यह वास्तव में एक अनियमित अंडाकार (अंडकोष) है, जिसमें डेंट हैं)। वहाँ कई मॉडल हैं, आगे की जानकारी विकी के लिए। एक महत्वपूर्ण मुद्दा यह है कि आप इस क्षेत्र को एक विमान मानेंगे या नहीं। सामान्य तौर पर, "छोटे" क्षेत्र, जहां अंक कुछ किमी तक अलग होते हैं, अगर प्लैनर और उत्तल पर विचार नहीं करते हैं तो महत्वपूर्ण त्रुटि उत्पन्न नहीं होगी।



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

सुनिश्चित करें कि आप त्रिकोण क्षेत्र को नकारात्मक करते हैं यदि अगला बिंदु "पीछे" बढ़ रहा है।
पुनरावर्ती

1

त्रिभुज की तुलना में बेहतर कार्टेशियन स्पेस में ट्रेपोज़िड्स को समेटना है:

area = 0;
for (i = 0; i < n; i++) {
  i1 = (i + 1) % n;
  area += (vertex[i].y + vertex[i1].y) * (vertex[i1].x - vertex[i].x) / 2.0;
}

1

शॉलेस फार्मूले का कार्यान्वयन नेम्पी में किया जा सकता था। इन शीर्षकों को मानते हुए:

import numpy as np
x = np.arange(0,1,0.001)
y = np.sqrt(1-x**2)

हम क्षेत्र को खोजने के लिए निम्नलिखित फ़ंक्शन को परिभाषित कर सकते हैं:

def PolyArea(x,y):
    return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1)))

और परिणाम प्राप्त कर रहे हैं:

print PolyArea(x,y)
# 0.26353377782163534

लूप से बचने से यह फंक्शन ~ 50X से तेज हो जाता है PolygonArea:

%timeit PolyArea(x,y)
# 10000 loops, best of 3: 42 µs per loop
%timeit PolygonArea(zip(x,y))
# 100 loops, best of 3: 2.09 ms per loop

नोट: मैंने एक अन्य प्रश्न के लिए यह उत्तर लिखा था , मैं इसका समाधान करने के लिए पूरी सूची के लिए यहाँ उल्लेख करता हूँ।


0

मेरा झुकाव बस त्रिकोणों को बंद करना शुरू करना होगा। मैं नहीं देखता कि कुछ और कैसे भयानक बालों से बचने के लिए कर सकता है।

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


इसके बारे में बालों का हिस्सा यह है कि यदि आपके तीन लगातार बिंदु एक त्रिकोण को बाहर या आंशिक रूप से बहुभुज के बाहर परिभाषित करते हैं, तो आपको एक समस्या है।
रिचर्ड

@ रीचर्ड: इसीलिए योग्यता 180 डिग्री के बारे में। यदि आप बहुभुज के बाहर एक त्रिभुज को काटते हैं तो आप कई डिग्री तक समाप्त हो जाएंगे।
लोरेन Pechtel

आपको बेहतर वर्णन करने की आवश्यकता हो सकती है कि आप कोण कैसे पा रहे हैं। समतल ज्यामिति में त्रिभुज के भाग के रूप में 3 अंक होने का कोई तरीका नहीं है और कोणों का कोई भी कोण या संयोजन 180 डिग्री से अधिक है - चेक व्यर्थ प्रतीत होगा।
रिचर्ड

@ रीचर्ड: आपके बहुभुज पर आपके पास हर जंक्शन का कोण है। यदि संबंधित त्रिभुज बहुभुज के बाहर स्थित होगा, तो दोनों खंडों के बीच का कोण 180 डिग्री से अधिक होगा।
लोरेन Pechtel

आपका मतलब है कि दो आसन्न किनारे खंडों का आंतरिक कोण 180 डिग्री से अधिक होगा।
रिचर्ड

0

सी करने का तरीका:

float areaForPoly(const int numVerts, const Point *verts)
{
    Point v2;
    float area = 0.0f;

    for (int i = 0; i<numVerts; i++){
        v2 = verts[(i + 1) % numVerts];
        area += verts[i].x*v2.y - verts[i].y*v2.x;
    }

    return area / 2.0f;
}

0

पायथन कोड

जैसा यहाँ वर्णित है: http://www.wikihow.com/Calculate-the-Area-of-a-Polygon

पांडा के साथ

import pandas as pd

df = pd.DataFrame({'x': [10, 20, 20, 30, 20, 10, 0], 'y': [-10, -10, -10, 0, 10, 30, 20]})
df = df.append(df.loc[0])

first_product = (df['x'].shift(1) * df['y']).fillna(0).sum()
second_product = (df['y'].shift(1) * df['x']).fillna(0).sum()

(first_product - second_product) / 2
600

0

मैं 2d बहुभुज के क्षेत्र की गणना के लिए कुछ सरल कार्य देने जा रहा हूं। यह उत्तल और अवतल बहुभुज दोनों के लिए काम करता है। हम बस बहुभुज को कई उप-त्रिकोणों में विभाजित करते हैं।

//don't forget to include cmath for abs function
struct Point{
  double x;
  double y;
}
// cross_product
double cp(Point a, Point b){ //returns cross product
  return a.x*b.y-a.y*b.x;
}

double area(Point * vertices, int n){  //n is number of sides
  double sum=0.0;
  for(i=0; i<n; i++){
    sum+=cp(vertices[i], vertices[(i+1)%n]); //%n is for last triangle
  }
  return abs(sum)/2.0;
}

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