दो आयतों के प्रतिच्छेदन का पता लगाने के लिए एल्गोरिथम?


143

मैं यह पता लगाने के लिए एक एल्गोरिथ्म की तलाश कर रहा हूं कि क्या दो आयतें प्रतिच्छेद करती हैं (एक एक मनमाना कोण पर, दूसरा केवल ऊर्ध्वाधर / क्षैतिज रेखाओं के साथ)।

परीक्षण अगर एक का एक कोने अन्य ALMOST कार्यों में है। यह विफल हो जाता है यदि आयताकार एक क्रॉस जैसी आकृति बनाते हैं।

यह लाइनों के ढलान का उपयोग करने से बचने के लिए एक अच्छा विचार है, जो ऊर्ध्वाधर लाइनों के लिए विशेष मामलों की आवश्यकता होगी।


क्या होगा यदि आप अपने कोने की जांच में जोड़ते हैं, तो यह देखने के लिए एक जांच कि क्या दूसरी आयत कोणीय आयत की सीमा (आयताकार) के अंदर है?
वेस पी।

आप किस भाषा में ऐसा करने जा रहे हैं? क्योंकि जावा में अंतर्निहित कक्षाएं हैं जो आपको ऐसा करने देती हैं।
मार्टिन

मुझे लगता है कि ग्राफिक्स एपीआई और अधिकांश जीयूआई लाइब्रेरी (जैसे स्विंग) ने इसे लागू किया है।
l_39217_l

उन मामलों को याद कर सकते हैं जहां वे ओवरलैप करते हैं, लेकिन कोई भी कोने किसी भी आयत के अंदर नहीं है
फ्लोरियन बॉश

1
यह प्रश्न लगभग समान है: stackoverflow.com/questions/306316/… । हालांकि, यह एक समाधान की तलाश में है जो विशेष रूप से C ++ के लिए है। स्वीकृत उत्तर भी बहुत सरल और सीधा है।
सिल्वर गोंजालेस

जवाबों:


162

मानक विधि अलग-अलग अक्ष परीक्षण करना होगा (उस पर एक Google खोज करें)।

संक्षेप में:

  • यदि आप दो वस्तुओं को अलग करने वाली रेखा पा सकते हैं तो दो वस्तुएं प्रतिच्छेद नहीं करती हैं। उदाहरण के लिए, ऑब्जेक्ट के सभी बिंदु रेखा के अलग-अलग पक्षों पर होते हैं।

मज़ेदार बात यह है, कि यह दो आयतों के सभी किनारों की जाँच करने के लिए पर्याप्त है। यदि आयताकार किनारों में से एक को ओवरलैप नहीं करता है, तो अलग-अलग अक्ष होगा।

2 डी में आप ढलान का उपयोग किए बिना ऐसा कर सकते हैं। एक छोर को केवल दो कोने के बीच के अंतर के रूप में परिभाषित किया जाता है, जैसे

  edge = v(n) - v(n-1)

आप इसे 90 ° से घुमाकर लम्बवत प्राप्त कर सकते हैं। 2 डी में यह आसान है:

  rotated.x = -unrotated.y
  rotated.y =  unrotated.x

तो कोई त्रिकोणमिति या ढलान शामिल नहीं है। वेक्टर को यूनिट-लंबाई के लिए सामान्य करना भी आवश्यक नहीं है।

यदि आप परीक्षण करना चाहते हैं कि क्या कोई बिंदु लाइन के एक या दूसरे पक्ष पर है तो आप बस डॉट-उत्पाद का उपयोग कर सकते हैं। संकेत आपको बताएगा कि आप किस पक्ष में हैं:

  // rotated: your rotated edge
  // v(n-1) any point from the edge.
  // testpoint: the point you want to find out which side it's on.

  side = sign (rotated.x * (testpoint.x - v(n-1).x) + 
               rotated.y * (testpoint.y - v(n-1).y);

अब आयत B के किनारों के विपरीत आयत A के सभी बिंदुओं का परीक्षण करें और इसके विपरीत। यदि आप एक अलग किनारा पाते हैं, तो ऑब्जेक्ट्स इंटरसेक्ट नहीं होते हैं (बी में अन्य सभी बिंदुओं को प्रदान करते हुए किनारे के दूसरी तरफ परीक्षण किए जा रहे हैं - नीचे ड्राइंग देखें)। यदि आपको कोई अलग किनारा नहीं मिलता है तो या तो आयत प्रतिच्छेद कर रहे हैं या एक आयत दूसरे में समाहित है।

परीक्षण किसी भी उत्तल बहुभुज btw के साथ काम करता है ..

संशोधन: एक अलग किनारे की पहचान करने के लिए, एक आयत के सभी बिंदुओं को दूसरे के प्रत्येक किनारे के परीक्षण के लिए पर्याप्त नहीं है। उम्मीदवार का किनारा E (नीचे) को एक अलग किनारे के रूप में पहचाना जाएगा, क्योंकि A के सभी बिंदु E के एक ही आधे तल में हैं। हालांकि, यह एक अलग किनारा नहीं है क्योंकि ख का Vb1 और Vb2 उस आधे विमान में भी हैं। यह केवल एक अलग किनारे होता अगर ऐसा न होता http://www.iassess.com/collision.png


2
यह एल्गोरिथ्म सभी मामलों के लिए काम नहीं करता है। दूसरी आयत को पहले आयत में 45 डिग्री घुमाया जाना और विकर्ण के साथ ऑफसेट करना संभव है ताकि यह ऊपर के चौराहे परीक्षणों को पूरा करे लेकिन प्रतिच्छेदन नहीं करता है।
स्किज़

6
स्किज़, सभी आठ किनारों की जांच करें। यदि ऑब्जेक्ट आठ किनारों में से एक को नहीं काटते हैं तो वे अलग हो जाएंगे। आप अपना मामला दिखाने वाली छवि पोस्ट क्यों नहीं करते? मैं तुम्हें धुरी दिखा सकता हूँ ..
Nils Pipenbrinck

2
मेरी गलती, यह उस स्थिति का सामना करती है।
स्किज़

2
छवि अब मर चुकी है (nov 2012)
जॉन ड्वोरक

2
मुझे इसे देखने में बहुत परेशानी हुई, इसलिए मुझे लगता है कि मुझे लगता है कि संदर्भित छवि को देखा जा रहा है। imgur.com/bNwrzsv
Rjdlee

16

मूल रूप से निम्नलिखित चित्र देखें:


यदि दो बक्से टकराते हैं, तो A और B रेखाएँ ओवरलैप होंगी।

ध्यान दें कि यह एक्स और वाई अक्ष दोनों पर किया जाना चाहिए, और दोनों को टकराने के लिए आयतों के लिए ओवरलैप करने की आवश्यकता है।

Gamasutra.com में एक अच्छा लेख है जो प्रश्न का उत्तर देता है (चित्र लेख से है)। मैंने 5 साल पहले इसी तरह का एल्गोरिथ्म किया था और बाद में इसे पोस्ट करने के लिए मुझे अपना कोड स्निपेट ढूंढना होगा

संशोधन : THE अलग एक्सिस प्रमेय कहा गया है कि दो उत्तल आकार नहीं है ओवरलैप अगर एक अलग अक्ष मौजूद है (यानी एक जहाँ दिखाया गया है अनुमानों नहीं ओवरलैप)। तो "एक अलग अक्ष मौजूद है" => "कोई ओवरलैप नहीं"। यह द्वि-निहितार्थ नहीं है, इसलिए आप इस निष्कर्ष को समाप्त नहीं कर सकते।


1
जाहिर है, चूंकि दो वर्ग (0,0,1,1) और (0,3,1,4) ओवरलैप नहीं करते हैं, लेकिन एक्स अक्ष पर उनके अनुमान पूरी तरह से ओवरलैप होते हैं। दोनों परीक्षण आवश्यक हैं, संयोजन पर्याप्त है।
MSalters

18
यह ओवरलैप करने के लिए x और y अनुमानों के लिए पर्याप्त नहीं है: उदाहरण के लिए आयतों को लें [(0,0), (0,3), (3,3), (3,0)] और [(2,5), (5,2), (7,4), (4,7)]।
योएल

4
मैं Gö में @Joel से सहमत हूं। यह विधि उन मामलों के एक बड़े समूह को याद करती है जहां आयतें ओवरलैप नहीं होती हैं, फिर भी उनके अनुमानित रेडिए एक्स और वाई दोनों में करते हैं।
स्कूटी टी

5
यह उत्तर गलत नहीं है, लेकिन यह भ्रामक है। यह सच है कि: यदि दो बक्से टकराते हैं, तो लाइनें A और B ओवरलैप होंगी। लेकिन यह भी सच है कि: यदि लाइनें A और B ओवरलैप करती हैं, तो दोनों बॉक्स टकरा सकते हैं या नहीं भी
मैट 10-30

7
@ फ्लोटर: मैं कहूंगा कि यह न केवल गलत है, बल्कि भ्रामक भी है , जो और भी बुरा है।
ब्लूराज -

4

m_pGladiator का जवाब सही है और मैं इसे पसंद करता हूं। आयत ओवरलैप का पता लगाने के लिए अलग-अलग अक्ष परीक्षण सबसे सरल और मानक तरीका है। एक पंक्ति जिसके लिए प्रक्षेपण अंतराल ओवरलैप नहीं है हम एक अलग अक्ष कहते हैं । Nils Pipenbrinck का समाधान बहुत सामान्य है। यह जांचने के लिए डॉट उत्पाद का उपयोग करता है कि क्या एक आकार दूसरे के किनारे के एक तरफ पूरी तरह से है। यह समाधान वास्तव में एन-किनारे उत्तल बहुभुज के लिए प्रेरित कर सकता है। हालाँकि, इसे दो आयतों के लिए ऑप्टिमाइज़ नहीं किया गया है।

m_pGladiator के उत्तर का महत्वपूर्ण बिंदु यह है कि हमें दोनों एक्साइज (एक्स और वाई) पर दो आयतों के प्रक्षेपण की जांच करनी चाहिए। यदि दो अनुमानों को ओवरलैप किया जाता है, तो हम कह सकते हैं कि ये दोनों आयतें ओवरलैप्ड हैं। तो m_pGladiator के जवाब के ऊपर की टिप्पणियां गलत हैं।

साधारण स्थिति के लिए, यदि दो आयतों को घुमाया नहीं जाता है, तो हम संरचना के साथ एक आयत प्रस्तुत करते हैं:

struct Rect {
    x, // the center in x axis
    y, // the center in y axis
    width,
    height
}

हम आयत A, B को recta, rectB के साथ नाम देते हैं।

    if Math.abs(rectA.x - rectB.x) < (Math.abs(rectA.width + rectB.width) / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(rectA.height + rectB.height) / 2))
    then
        // A and B collide
    end if

यदि दो आयतों में से किसी एक को घुमाया जाता है, तो इसे x और y एक्सिस पर उनके प्रक्षेपण को निर्धारित करने के लिए कुछ प्रयासों की आवश्यकता हो सकती है। निम्नलिखित के रूप में संरचनात्मक घुमाएँ परिभाषित करें:

struct RotatedRect : Rect {
    double angle; // the rotating angle oriented to its center
}

अंतर यह है कि चौड़ाई 'अब थोड़ी अलग है: चौड़ाई' रेक्टा के लिए: Math.sqrt(rectA.width*rectA.width + rectA.height*rectA.height) * Math.cos(rectA.angle) चौड़ाई बी 'रेक्टबी के लिए:Math.sqrt(rectB.width*rectB.width + rectB.height*rectB.height) * Math.cos(rectB.angle)

    if Math.abs(rectA.x - rectB.x) < (Math.abs(widthA' + widthB') / 2) 
&& (Math.abs(rectA.y - rectB.y) < (Math.abs(heightA' + heightB') / 2))
    then
        // A and B collide
    end if

जीडीसी (गेम डेवलपमेंट कॉन्फ्रेंस 2007) पीपीटी www.realtimecollisiondetection.net/pubs/GDC07_Ericson_Physics_Tutorial_SAT.ppt को संदर्भित कर सकता है


नकारात्मक चौड़ाई को संभालने के लिए आपको "Math.abs (rectA.width + rectB.width)" में Math.abs () की आवश्यकता क्यों है?
एलेक्सविलेन

पृथक्करण अक्ष आवश्यक रूप से कम्पास दिशा नहीं है, इसका कोई भी कोण हो सकता है।
बेन वोइगट

नॉन-रोटेटेड आयतें rectA (x = 0, y = 0, चौड़ाई = 1, ऊँचाई = 1) और rectB (x = 2, y = 0, चौड़ाई = 100, ऊँचाई = 1) प्रतिच्छेद नहीं करते हैं, लेकिन आपकी विधि कहती है कि वे एक दूसरे को काटना। क्या मुझसे कुछ गलत हो रही है?
कागमी सास्का रोशलाइट

4

कोको में आप आसानी से पता लगा सकते हैं कि क्या चयनित एरेआस आपके घुमाए गए NSView के फ्रेम रेक्ट को इंटरसेक्ट करता है। तुम भी बहुभुज, मानदंड की गणना करने की जरूरत नहीं है एक ऐसे। बस इन विधियों को अपने NSView उपवर्ग में जोड़ें। उदाहरण के लिए, उपयोगकर्ता NSView के पर्यवेक्षण पर एक क्षेत्र का चयन करता है, फिर आप विधि को कहते हैं। एपीआई कन्वर्टरैक्ट: वह काम करेगा। जब आप इसे चुनने के लिए NSView पर क्लिक करते हैं तो वही ट्रिक काम करती है। उस मामले में बस नीचे के रूप में हिटटेस्ट विधि को ओवरराइड करें। API कनवर्ज़न: यह काम करेगा ;-)

- (BOOL)DoesThisRectSelectMe:(NSRect)selectedArea
{
    NSRect localArea = [self convertRect:selectedArea fromView:self.superview];

    return NSIntersectsRect(localArea, self.bounds);
}


- (NSView *)hitTest:(NSPoint)aPoint
{
    NSPoint localPoint = [self convertPoint:aPoint fromView:self.superview];
    return NSPointInRect(localPoint, self.bounds) ? self : nil;
}

2
यह कोड केवल आयतों के लिए काम करता है जो स्क्रीन पर वर्गाकार होते हैं। यह एक तुच्छ मामला है। धारणा यह है कि हम आयतों के साथ काम कर रहे हैं जो स्क्रीन या एक दूसरे के लिए 90 डिग्री के कोण पर नहीं हैं।
डंकन सी

जैसा कि मैंने अपने अनुप्रयोगों में जाँच और उपयोग किया है, वह कोड किसी भी घुमाए गए आयत पर काम करता है। कोई फर्क नहीं पड़ता रोटेशन की डिग्री।
लियोनार्डो

यह एल्गोरिथ्म का वर्णन नहीं करता है, हालांकि, यह सिर्फ एक पुस्तकालय का उल्लेख करता है जो पहले से ही इसका उपयोग करता है।
बेन वोइगट

2

यह देखने के लिए जांचें कि क्या आयत में से कोई भी रेखा दूसरे से किसी भी रेखा को काटती है। Naive line सेगमेंट चौराहे को कोड करना आसान है।

यदि आपको अधिक गति की आवश्यकता है, तो लाइन सेगमेंट चौराहे (स्वीप-लाइन) के लिए उन्नत एल्गोरिदम हैं। Http://en.wikipedia.org/wiki/Line_segment_intersection देखें


4
सावधान! उस मामले को न भूलें जहां एक आयत पूरी तरह से दूसरे को घेर
लेती है

2

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

वेब पर नो फिट बहुभुज की खोज करें और देखें कि क्या आप उत्तल बहुभुजों के लिए एक एल्गोरिथ्म पा सकते हैं (यदि आपके पास अवतल बहुभुज हैं तो यह अधिक जटिल हो जाता है)। अगर आपको कुछ नहीं मिल रहा है तो मुझे हावर्ड डॉट जे डॉट जीमेल डॉट कॉम पर ईमेल कर सकते हैं


1

यहाँ मुझे लगता है कि सभी संभावित मामलों का ध्यान रखा जाएगा। निम्नलिखित परीक्षण करें।

  1. आयत 1 के किसी भी कोने की जाँच करें 1 आयत 2 के अंदर और इसके विपरीत। कभी भी आपको एक ऐसी जगह मिलती है, जो दूसरी आयत के अंदर रहती है, जिससे आप यह निष्कर्ष निकाल सकते हैं कि वे खोज को रोकते हैं और रोकते हैं। एक दूसरे के अंदर पूरी तरह से रहने वाले आयत का ख्याल रखेगा।
  2. यदि उपरोक्त परीक्षण अनिर्णायक है, तो 1 आयत की प्रत्येक पंक्ति के दूसरे बिंदु की प्रत्येक रेखा के साथ प्रतिच्छेदन बिंदु ज्ञात कीजिए। एक बार चौराहे के एक बिंदु की जांच हो जाने के बाद यदि यह संबंधित 4 बिंदुओं द्वारा बनाई गई काल्पनिक आयत के अंदर रहता है। जब कभी ऐसा बिंदु मिलता है तो यह निष्कर्ष निकलता है कि वे खोज को रोकते हैं और रोकते हैं।

यदि उपरोक्त 2 परीक्षण झूठे हैं तो ये 2 आयतें ओवरलैप नहीं होती हैं।


0

यदि आप जावा का उपयोग कर रहे हैं, तो शेप इंटरफेस के सभी कार्यान्वयन में एक प्रतिच्छेदन विधि होती है जो एक आयत लेती है।


दुर्भाग्य से मैं C # का उपयोग कर रहा हूं। आयत वर्ग में एक समतुल्य () विधि है, लेकिन यह केवल गैर-घुमाए गए आयतों के लिए है।
user20493

चौराहों () विधि बहुत बेकार है क्योंकि यह मुझे लगता है कि चौराहे के बजाय बूलियन लौटाता है।
ZZ 5

0

खैर, जानवर बल विधि क्षैतिज आयत के किनारों पर चलना है और किनारे पर प्रत्येक बिंदु की जांच करके यह देखना है कि क्या यह या अन्य आयत पर पड़ता है।

गणितीय उत्तर दोनों आयतों के प्रत्येक किनारे का वर्णन समीकरण बनाने के लिए है। अब आप आसानी से पता लगा सकते हैं कि क्या आयत A से चार पंक्तियों में से कोई भी आयत B की किसी भी रेखा को काटती है, जो एक सरल (तेज) रैखिक समीकरण सॉल्वर होना चाहिए।

-Adam


2
समीकरणों के साथ समस्या तब होती है जब आपके पास एक ऊर्ध्वाधर रेखा होती है, जिसमें अनंत ढलान होती है।
user20493

हर समाधान के लिए कोने मामले हैं।
एडम डेविस

2
और एक वर्ग पूरी तरह से दूसरे को घेरता है।
ओलिवर हल्लम

0

आप अक्ष-संरेखित एक के प्रत्येक पक्ष के साथ कोण आयत के प्रत्येक पक्ष के चौराहे को पा सकते हैं। ऐसा अनंत रेखा के समीकरण का पता लगाकर करें, जिस पर प्रत्येक पक्ष निहित है (यानी v1 + t (v2-v1) और v'1 + t '(v'2-v'1) मूल रूप से), जिस बिंदु पर खोज जब वे दो समीकरण बराबर होते हैं (यदि वे समानांतर हैं, तो आप उसके लिए परीक्षण कर सकते हैं) और फिर परीक्षण कर सकते हैं कि क्या बिंदु दो खंडों के बीच रेखा खंड पर स्थित है, अर्थात क्या यह सत्य है कि 0 <= t <= 1 और 0 <= t '<= 1।

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


0

इस समस्या के 3D संस्करण के लिए मैं यही करूंगा :

समीकरण P1 और P2 द्वारा वर्णित विमानों के रूप में 2 आयतों को मॉडल करें, फिर P1 = P2 लिखें और उस चौराहे समीकरण की रेखा से व्युत्पन्न करें, जो तब मौजूद नहीं होगा जब विमान समानांतर (कोई चौराहा) नहीं हैं, या एक ही विमान में हैं, जिस स्थिति में आपको 0 = 0 मिलता है। उस मामले में आपको एक 2 डी आयत चौराहे एल्गोरिदम को नियोजित करना होगा।

तब मैं देखूंगा कि क्या वह रेखा, जो दोनों आयतों के तल में है, दोनों आयतों से होकर गुजरती है। यदि ऐसा होता है, तो आपके पास 2 आयतों का एक चौराहा होता है, अन्यथा आप नहीं (या नहीं, मैं अपने सिर में एक कोने का मामला याद कर सकता था)।

यह पता लगाने के लिए कि क्या कोई रेखा उसी प्लेन में आयत से होकर गुजरती है, मुझे लाइन के प्रतिच्छेदन के 2 बिंदु और आयत के किनारे मिलेंगे (लाइन समीकरणों का उपयोग करके उन्हें मॉडलिंग करना), और फिर सुनिश्चित करें कि चौराहों के बिंदु अंदर हैं रेंज।

यह गणितीय वर्णन है, दुर्भाग्य से मेरे पास उपरोक्त करने के लिए कोई कोड नहीं है।


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

0

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

यह एल्गोरिथ्म अलग करने वाले अक्ष परीक्षण की तुलना में कुछ अधिक लंबा है, लेकिन यह तेज है क्योंकि इसे केवल एक आधे-विमान परीक्षण की आवश्यकता होती है यदि किनारों को दो क्वाड्रंट पार कर रहे हैं (अलग अक्ष विधि का उपयोग करके 32 परीक्षणों तक विरोध किया गया)

एल्गोरिथ्म का आगे का लाभ है कि इसका उपयोग किसी भी बहुभुज (उत्तल या अवतल) के ओवरलैप का परीक्षण करने के लिए किया जा सकता है । जहाँ तक मुझे पता है, एल्गोरिथ्म केवल 2D स्पेस में काम करता है।


3
मैं गलत हो सकता हूं, लेकिन क्या यह जांच नहीं करता है कि एक आयत के कोने दूसरे के अंदर हैं? यदि हाँ, तो यह पर्याप्त नहीं है क्योंकि आयतें बिना किसी कोने के ओवरलैप हो सकती हैं।
सिनैलॉ

क्या वे, आयतों के साथ? कैसे? यह मुझे लगता है कि 2 आयतों को प्रतिच्छेद करने के लिए, आयतों में से किसी एक के कम से कम एक शीर्ष को दूसरी आयत पर रखना चाहिए।
डंकन सी

@ डंकन: हाँ, वे कर सकते हैं। पलटवार एक क्रॉस है, और इसे मूल प्रश्न में भी सूचीबद्ध किया गया था।
बेन Voigt

@BenVoigt यह एक बहुत पुराना धागा है, लेकिन आप बिलकुल सही हैं।
डंकन सी

0

या तो मैं कुछ और याद कर रहा हूं कि यह इतना जटिल क्यों है?

यदि (X1, y1) और (X1, Y1) आयतों के कोने हैं, तो चौराहा खोजने के लिए करें:

    xIntersect = false;
    yIntersect = false;
    if (!(Math.min(x1, x2, x3, x4) > Math.max(X1, X2, X3, X4) || Math.max(x1, x2, x3, x4) < Math.min(X1, X2, X3, X4))) xIntersect = true;
    if (!(Math.min(y1, y2, y3, y4) > Math.max(Y1, Y2, Y3, Y4) || Math.max(y1, y2, y3, y4) < Math.min(Y1, Y2, Y3, Y4))) yIntersect = true;
    if (xIntersect && yIntersect) {alert("Intersect");}

3
आप याद कर रहे हैं कि वह चाहता है कि एक मनमाना कोण द्वारा घुमाया जाए।
रोबॉटबग्स

0

मैंने इसे इस तरह लागू किया:

bool rectCollision(const CGRect &boundsA, const Matrix3x3 &mB, const CGRect &boundsB)
{
    float Axmin = boundsA.origin.x;
    float Axmax = Axmin + boundsA.size.width;
    float Aymin = boundsA.origin.y;
    float Aymax = Aymin + boundsA.size.height;

    float Bxmin = boundsB.origin.x;
    float Bxmax = Bxmin + boundsB.size.width;
    float Bymin = boundsB.origin.y;
    float Bymax = Bymin + boundsB.size.height;

    // find location of B corners in A space
    float B0x = mB(0,0) * Bxmin + mB(0,1) * Bymin + mB(0,2);
    float B0y = mB(1,0) * Bxmin + mB(1,1) * Bymin + mB(1,2);

    float B1x = mB(0,0) * Bxmax + mB(0,1) * Bymin + mB(0,2);
    float B1y = mB(1,0) * Bxmax + mB(1,1) * Bymin + mB(1,2);

    float B2x = mB(0,0) * Bxmin + mB(0,1) * Bymax + mB(0,2);
    float B2y = mB(1,0) * Bxmin + mB(1,1) * Bymax + mB(1,2);

    float B3x = mB(0,0) * Bxmax + mB(0,1) * Bymax + mB(0,2);
    float B3y = mB(1,0) * Bxmax + mB(1,1) * Bymax + mB(1,2);

    if(B0x<Axmin && B1x<Axmin && B2x<Axmin && B3x<Axmin)
        return false;
    if(B0x>Axmax && B1x>Axmax && B2x>Axmax && B3x>Axmax)
        return false;
    if(B0y<Aymin && B1y<Aymin && B2y<Aymin && B3y<Aymin)
        return false;
    if(B0y>Aymax && B1y>Aymax && B2y>Aymax && B3y>Aymax)
        return false;

    float det = mB(0,0)*mB(1,1) - mB(0,1)*mB(1,0);
    float dx = mB(1,2)*mB(0,1) - mB(0,2)*mB(1,1);
    float dy = mB(0,2)*mB(1,0) - mB(1,2)*mB(0,0);

    // find location of A corners in B space
    float A0x = (mB(1,1) * Axmin - mB(0,1) * Aymin + dx)/det;
    float A0y = (-mB(1,0) * Axmin + mB(0,0) * Aymin + dy)/det;

    float A1x = (mB(1,1) * Axmax - mB(0,1) * Aymin + dx)/det;
    float A1y = (-mB(1,0) * Axmax + mB(0,0) * Aymin + dy)/det;

    float A2x = (mB(1,1) * Axmin - mB(0,1) * Aymax + dx)/det;
    float A2y = (-mB(1,0) * Axmin + mB(0,0) * Aymax + dy)/det;

    float A3x = (mB(1,1) * Axmax - mB(0,1) * Aymax + dx)/det;
    float A3y = (-mB(1,0) * Axmax + mB(0,0) * Aymax + dy)/det;

    if(A0x<Bxmin && A1x<Bxmin && A2x<Bxmin && A3x<Bxmin)
        return false;
    if(A0x>Bxmax && A1x>Bxmax && A2x>Bxmax && A3x>Bxmax)
        return false;
    if(A0y<Bymin && A1y<Bymin && A2y<Bymin && A3y<Bymin)
        return false;
    if(A0y>Bymax && A1y>Bymax && A2y>Bymax && A3y>Bymax)
        return false;

    return true;
}

मैट्रिक्स mB किसी भी परिशोधित मैट्रिक्स है जो B स्पेस को A स्पेस में पॉइंट्स में कनवर्ट करता है। इसमें सरल रोटेशन और अनुवाद, रोटेशन प्लस स्केलिंग, और पूर्ण चक्कर वाले युद्ध शामिल हैं, लेकिन परिप्रेक्ष्य युद्ध नहीं।

यह यथासंभव इष्टतम नहीं हो सकता है। गति कोई बहुत बड़ी चिंता नहीं थी। हालांकि यह मेरे लिए ठीक काम करने लगता है।


0

यहाँ स्वीकृत उत्तर का एक matlab कार्यान्वयन है:

function olap_flag = ol(A,B,sub)

%A and B should be 4 x 2 matrices containing the xy coordinates of the corners in clockwise order

if nargin == 2
  olap_flag = ol(A,B,1) && ol(B,A,1);
  return;
end

urdl = diff(A([1:4 1],:));
s = sum(urdl .* A, 2);
sdiff = B * urdl' - repmat(s,[1 4]);

olap_flag = ~any(max(sdiff)<0);

0

यह पारंपरिक विधि है, लाइन से लाइन पर जाएं और जांचें कि क्या रेखाएं प्रतिच्छेद कर रही हैं। यह MATLAB में कोड है।

C1 = [0, 0];    % Centre of rectangle 1 (x,y)
C2 = [1, 1];    % Centre of rectangle 2 (x,y)
W1 = 5; W2 = 3; % Widths of rectangles 1 and 2
H1 = 2; H2 = 3; % Heights of rectangles 1 and 2
% Define the corner points of the rectangles using the above
R1 = [C1(1) + [W1; W1; -W1; -W1]/2, C1(2) + [H1; -H1; -H1; H1]/2];
R2 = [C2(1) + [W2; W2; -W2; -W2]/2, C2(2) + [H2; -H2; -H2; H2]/2];

R1 = [R1 ; R1(1,:)] ;
R2 = [R2 ; R2(1,:)] ;

plot(R1(:,1),R1(:,2),'r')
hold on
plot(R2(:,1),R2(:,2),'b')


%% lines of Rectangles 
L1 = [R1(1:end-1,:) R1(2:end,:)] ;
L2 = [R2(1:end-1,:) R2(2:end,:)] ;
%% GEt intersection points
P = zeros(2,[]) ;
count = 0 ;
for i = 1:4
    line1 = reshape(L1(i,:),2,2) ;
    for j = 1:4
        line2 = reshape(L2(j,:),2,2) ;
        point = InterX(line1,line2) ;
        if ~isempty(point)
            count = count+1 ;
            P(:,count) = point ;
        end
    end
end
%%
if ~isempty(P)
    fprintf('Given rectangles intersect at %d points:\n',size(P,2))
    plot(P(1,:),P(2,:),'*k')
end

समारोह InterX से डाउनलोड किया जा सकता है: https://in.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections?focused=5165138&tab=function


0

मेरे पास अपनी खुद की एक सरल विधि है, अगर हमारे पास 2 आयतें हैं:

R1 = (min_x1, max_x1, min_y1, max_y1)

R2 = (min_x2, max_x2, min_y2, max_y2)

वे ओवरलैप करते हैं यदि और केवल यदि:

ओवरलैप = (max_x1> min_x2) और (max_x2> min_x1) और (max_y1> min_y2) और (max_y2> min_y1)

आप इसे 3 डी बॉक्स के लिए भी कर सकते हैं, वास्तव में यह किसी भी संख्या में आयामों के लिए काम करता है।


0

अन्य उत्तरों में पर्याप्त कहा गया है, इसलिए मैं बस एक-लाइनर pseudocode जोड़ूंगा:

!(a.left > b.right || b.left > a.right || a.top > b.bottom || b.top > a.bottom);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.