मैं जटिल बहुभुजों को कैसे संयोजित करूं?


83

दो बहुभुज दिए गए:

POLYGON((1 0, 1 8, 6 4, 1 0))
POLYGON((4 1, 3 5, 4 9, 9 5, 4 1),(4 5, 5 7, 6 7, 4 4, 4 5))

मैं संघ (संयुक्त बहुभुज) की गणना कैसे कर सकता हूं?

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

डेव का उदाहरण संघ का उत्पादन करने के लिए SQL सर्वर का उपयोग करता है, लेकिन मुझे कोड में समान पूरा करने की आवश्यकता है। मैं किसी भी भाषा में गणितीय सूत्र या कोड उदाहरण की तलाश कर रहा हूं जो वास्तविक गणित को उजागर करता है। मैं उन मानचित्रों का निर्माण करने का प्रयास कर रहा हूं जो देशों को गतिशील रूप से क्षेत्रों में मिलाते हैं। मैंने यहां एक संबंधित प्रश्न पूछा: भौगोलिक आकृतियों को समूहीकृत करना

जवाबों:


70

यह एक बहुत अच्छा सवाल है। मैंने कुछ समय पहले सी # पर एक ही एल्गोरिदम लागू किया था। एल्गोरिथ्म दो बहुभुजों का एक सामान्य समोच्च बनाता है (यानी छेद के बिना एक संघ का निर्माण करता है)। यही पर है।


लक्ष्य

चरण 1. पॉलीगनों का वर्णन करने वाला ग्राफ़ बनाएं।

इनपुट: पहला बहुभुज (n अंक), दूसरा बहुभुज (m अंक)। आउटपुट: ग्राफ। वर्टेक्स - चौराहे के बिंदु का बहुभुज बिंदु।

हमें चौराहों को ढूंढना चाहिए। दोनों बहुभुज [O (n * m)] में सभी बहुभुज पक्षों के माध्यम से प्रवेश करें और किसी भी चौराहों को ढूंढें।

  • यदि एक चौराहा नहीं मिला है, तो बस कोने जोड़ें और उन्हें किनारे से कनेक्ट करें।

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

चरण 2. निर्मित ग्राफ की जाँच करें

यदि ग्राफ़ बनाते समय हमें कोई प्रतिच्छेदन बिंदु नहीं मिला, तो हमारे पास निम्नलिखित में से एक स्थिति है:

  1. पॉलीगोन 1 में पॉलीगॉन 2 - रिटर्न पॉलीगॉन 1 होता है
  2. पॉलीगोन 2 में पॉलीगोन 1 - रिटर्न पॉलीगॉन 2 शामिल हैं
  3. बहुभुज 1 और बहुभुज 2 प्रतिच्छेद नहीं करते हैं। बहुभुज 1 और बहुभुज 2 लौटाएँ।

चरण 3. बाईं-बाईं ओर शीर्ष ढूंढें।

न्यूनतम x और y निर्देशांक (मिनएक्स, मिनी) का पता लगाएं। फिर (न्यूनतम, मिनी) और बहुभुज के बिंदुओं के बीच न्यूनतम दूरी का पता लगाएं। यह पॉइंट लेफ्ट-बॉटम पॉइंट होगा।

वाम-तल बिंदु

चरण 4. आम समोच्च का निर्माण।

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

अगला बिंदु चुनने के लिए, काउंटर-क्लॉकवाइज दिशा में अधिकतम आंतरिक कोण के साथ एक किनारे चुनें।

मैं दो वैक्टरों की गणना करता हूं: वर्तमान बढ़त के लिए वेक्टर 1 और प्रत्येक अगले अनिर्धारित किनारे के लिए वेक्टर 2 (जैसा कि चित्र में प्रस्तुत किया गया है)।

वैक्टर के लिए मैं गणना करता हूं:

  1. स्केलर उत्पाद (डॉट उत्पाद)। यह वैक्टर के बीच के कोण से संबंधित मान लौटाता है।
  2. वेक्टर उत्पाद (क्रॉस उत्पाद)। यह एक नया वेक्टर लौटाता है। यदि इस वेक्टर का z- समन्वय सकारात्मक है, तो स्केलर उत्पाद मुझे काउंटर-क्लॉकवाइज दिशा में सही कोण देता है। एल्स (z- समन्वय नकारात्मक है), मैं वैक्टर के बीच कोण को 360 के रूप में गणना करता हूं - स्केलर उत्पाद से कोण।

परिणामस्वरूप मुझे अधिकतम कोण के साथ एक किनारे (और एक अगला अगला शीर्ष) मिलता है।

मैं परिणाम सूची में प्रत्येक उत्तीर्ण शीर्ष को जोड़ता हूं। परिणाम सूची संघ बहुभुज है। वैक्टर

टिप्पणियों

  1. यह एल्गोरिथ्म हमें बहुभुज के कई विलय करने की अनुमति देता है - बहुभुज के जोड़े के साथ चलने के लिए।
  2. यदि आपके पास एक पथ है जिसमें कई बीज़ियर वक्र और रेखाएँ हैं, तो आपको पहले इस पथ को समतल करना चाहिए।

2
मुझे लगता है कि यह उल्लेख किया जाना चाहिए कि स्केलर उत्पादों की तुलना करने के लिए, अपने स्केलर उत्पाद की गणना करने से पहले वैक्टर को सामान्य किया जाना चाहिए (यानी, लंबाई द्वारा वेक्टर निर्देशांक को विभाजित करें)। किसी भी तरह, इस उत्तर के लिए धन्यवाद।
पलकबा

क्या इस एल्गोरिथ्म का कोई नाम है या आपकी खुद की रचना है?
एंड्रेस ओविदो

मैंने इसे कहीं पढ़ा है, लेकिन अब मुझे याद नहीं है कि कहां और कब =)
xtmq

नोट: छेद के बिना बहुभुज संघ देखें , जो एक अलग आरेख दिखाता है: दो बहुभुज ओवरलैप, लेकिन एक "छेद" है जिसमें से कोई भी कवर नहीं करता है। @ Xtmq की टिप्पणी के अनुसार, यह एल्गोरिथ्म उस छेद को "भरता है" (भले ही यह इनपुट बहुभुज का हिस्सा न हो )। यदि आप उन छेदों को छेद के रूप में "बनाए रखना" चाहते हैं, तो (ए) छेदों की गणना करें, और (बी) "छेदों के सेट" को लौटा दें [कुछ ग्राफिक्स सिस्टम / मोड पर, ये छेद आउटपुट बहुभुज सेट में शामिल किए जा सकते हैं। , और खींचे जाने पर छिद्रों में परिणत होगा।] ...
टूलमेकरसैट

2
... करने के लिए "(ए) छेदों की गणना करें", उन बिंदुओं की तलाश करें जो "चरण 4 द्वारा निर्मित नहीं हैं। सामान्य समोच्च का निर्माण करें"। छेद को "शुरू" करने के लिए इनमें से किसी एक बिंदु का उपयोग करें। एक समान "समोच्च" एल्गोरिथ्म करें, मुख्य आउटपुट बहुभुज द्वारा पहले से ही उपयोग किए गए किसी भी बिंदु को छोड़कर। परिणामी बहुभुज एक "छेद" है। तब तक दोहराएं जब तक कि सभी बिंदुओं को कुछ बहुभुज या छेद में शामिल नहीं किया गया हो।
टूलमेकरसैट

11

यह एक चुनौतीपूर्ण लेकिन अच्छी तरह से समझा जाने वाला विषय है, जो अक्सर "बहुभुजों पर नियमित बूलियन संचालन" नाम के तहत आता है। आप इस MathOverflow के उत्तर को देख सकते हैं , जिसमें नीचे का आंकड़ा ( एलन मुर्टा की क्लिपिंग लाइब्रेरी से ) शामिल है, गुलाबी संघ ओपी के संयोजन के साथ :


      बूलियनओप्स



2
इस आदमी ने शाब्दिक रूप से इस पर किताब लिखी है;)
कांस्टेंटिन

6

आपको यह निर्धारित करने की आवश्यकता है कि कौन से बिंदु अंदर झूठ बोलते हैं । इन बिंदुओं को हटाने के बाद, आप "बाहरी" बिंदुओं के एक सेट को दूसरे में सम्मिलित कर सकते हैं। आपके सम्मिलन बिंदु (जैसे कि आपके पास दाईं ओर चित्र में तीर है) वह जगह है जहां आपको इनपुट सेट से अंक निकालना था।


1
बोर्के से जोड़ने के लिए +1। तीस सेकंड धीमा और मैं इसे करने के लिए आप को पीटा होगा :)
डेविड Seiler

4

अच्छा प्रश्न! मैंने पहले कभी यह प्रयास नहीं किया है, लेकिन मैं अब इस पर दरार डालूंगा।

पहला: आपको यह जानना होगा कि ये दोनों आकृतियाँ कहाँ पर ओवरलैप हैं। ऐसा करने के लिए, आप बहुभुज ए में प्रत्येक किनारे को देख सकते हैं और देख सकते हैं कि यह कहाँ है और बहुभुज बी में किनारे। इस उदाहरण में, प्रतिच्छेदन के दो बिंदु होने चाहिए।

तब: संघ आकार बनाएं। आप ए और बी के सभी कोने ले सकते हैं, और चौराहे के बिंदु भी, और फिर अंतिम आकार द्वारा निहित कोने को बाहर कर सकते हैं। इन बिंदुओं को खोजने के लिए, ऐसा लगता है कि आप ए के किसी भी शीर्ष को पा सकते हैं जो कि बी के अंदर है, और बी का कोई भी भाग ए के साथ है।


हां असली सवाल यह है कि हम दो अंतर बिंदुओं की गणना कैसे करते हैं ?
पचेरियर


2

एक समाधान जो मैंने बीएसपी पेड़ों का उपयोग करके देखा है, वह यहां वर्णित है

मूल रूप से, यह बहुभुज के किनारों के एक संघ के संदर्भ में चौराहे का वर्णन करता है जो बहुभुज बी के अंदर होते हैं (आंशिक किनारों सहित, और बीएसपी के पेड़ का उपयोग करके गणना की जाती है )। उसके बाद, आप  /  बी को ~ (~  / \ ~ बी ) के रूप में परिभाषित कर सकते हैं , जहां ~ बहुभुज के घुमावदार को उलटता है, / और यूनियन को दर्शाता है और / \ _ प्रतिच्छेदन को दर्शाता है।


2

यह बहुत पुराना सवाल है लेकिन बूस्ट के Union_ फंक्शन ने मेरे लिए काम किया।

इस स्निपेट को नीचे देखें:

#include <iostream>
#include <vector>

#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

#include <boost/foreach.hpp>


int main()
{
    typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;

    polygon green, blue;

    boost::geometry::read_wkt(
        "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", green);

    boost::geometry::read_wkt(
        "POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))", blue);

    std::vector<polygon> output;
    boost::geometry::union_(green, blue, output);

    int i = 0;
    std::cout << "green || blue:" << std::endl;
    BOOST_FOREACH(polygon const& p, output)
    {
        std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;

        for (int i = 0; i < p.outer().size(); i++)
        {
            std::cout << p.outer().at(i).x() << " " << p.outer().at(i).y() << std::endl;
        }
    }



    return 0;
}

1
याद रखें यदि आपके पॉलीगोन "सही" हैं तो निस्सार। देखें stackoverflow.com/questions/22258784/...
anumi

1

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


2
"जब देशों का समूह होता है, तो मुझे उम्मीद है कि कोई अतिव्यापी नहीं होगा" ... सभी देश अपने या अपने पड़ोसी देशों की सीमाओं पर सहमत नहीं होते हैं, हालांकि यह अच्छा होगा यदि वे करते हैं।
FrustratedWithFormsDesigner

2
@FrustratedWithFormsDesigner वास्तव में, लेकिन अधिकांश कार्टोग्राफर या तो विवादित क्षेत्र को अपने राजनीतिक सहयोगी के रूप में या अपने आप में एक अलग इकाई के रूप में आवंटित करेंगे - यही कारण है कि मैं अपने एल्गोरिथ्म को भोले के रूप में वर्णित करता हूं ...
रोलैंड शैर


1

मैंने उसी समस्या का सामना किया है और मैंने निम्नलिखित तरीके का उपयोग करके समस्या को हल किया है

एंगस जॉनसन की क्लिपर लाइब्रेरी के सी ++ अनुवाद के लिए साइथन रैपर (देखें। 6.4.2) https://github.com/fonttools/pyclipper

pc = pyclipper.Pyclipper()
def get_poly_union(polygons):
    pc.AddPaths(polygons, pyclipper.PT_SUBJECT, True)
    solution = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
    return solution[0]

print_image = image.copy()
solution = get_poly_union(polygons_array) 
#polygons_array=[polygon,polygon,polygon, ...,polygon] and polygon=[point,point,point...,point]

cv2.drawContours(print_image, [np.asarray(solution)], -1, (0, 255, 0), 2)

plt.imshow(print_image)

क्लिपर c ++ में सीधे उपलब्ध है: angusj.com/delphi/clipper.php
Catskul
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.