सर्कल-लाइन टकराव का पता लगाने की समस्या


11

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

अधिकांश समय सर्किल-लाइन परीक्षण ठीक से काम करता है और टक्कर के बिंदुओं को सही ढंग से हल किया जाता है।

टकराव का सही तरीके से पता लगाना।

हालांकि, कभी-कभी मेरी टक्कर का पता लगाने वाला कोड एक नकारात्मक भेदभाव के कारण गलत हो जाता है जब गेंद वास्तव में ईंट को काट रही होती है।

टकराव का पता लगाना विफल।

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

/* 
 * from and to are points at the start and end of the convex polygons edge.
 * This function is called for every edge in the convex polygon until a
 * collision is detected. 
 */

bool circleLineCollision(Vec2f from, Vec2f to)
{
    Vec2f lFrom, lTo, lLine;
    Vec2f line, normal;
    Vec2f intersectPt1, intersectPt2;
    float a, b, c, disc, sqrt_disc, u, v, nn, vn;
    bool one = false, two = false;

    // set line vectors
    lFrom = from - ball.circle.centre;      // localised
    lTo = to - ball.circle.centre;          // localised
    lLine = lFrom - lTo;                    // localised
    line = from - to;

    // calculate a, b & c values
    a = lLine.dot(lLine);
    b = 2 * (lLine.dot(lFrom));
    c = (lFrom.dot(lFrom)) - (ball.circle.radius * ball.circle.radius);

    // discriminant
    disc = (b * b) - (4 * a * c);

    if (disc < 0.0f)
    {
        // no intersections
        return false;
    }
    else if (disc == 0.0f)
    {
        // one intersection
        u = -b / (2 * a);

        intersectPt1 = from + (lLine.scale(u));
        one = pointOnLine(intersectPt1, from, to);

        if (!one)
            return false;
        return true;
    }
    else
    {
        // two intersections
        sqrt_disc = sqrt(disc);
        u = (-b + sqrt_disc) / (2 * a);
        v = (-b - sqrt_disc) / (2 * a);
        intersectPt1 = from + (lLine.scale(u));
        intersectPt2 = from + (lLine.scale(v));

        one = pointOnLine(intersectPt1, from, to);
        two = pointOnLine(intersectPt2, from, to);

        if (!one && !two)
            return false;
        return true;
    }
}

bool pointOnLine(Vec2f p, Vec2f from, Vec2f to)
{
    if (p.x >= min(from.x, to.x) && p.x <= max(from.x, to.x) && 
        p.y >= min(from.y, to.y) && p.y <= max(from.y, to.y))
        return true;
    return false;
}

मुझे lLine और लाइन के बीच कोई अंतर नहीं मिल रहा है ...
FxIII

पॉइंटऑनलाइन परीक्षण को सरल बनाया जा सकता है और वास्तविक बिंदु की गणना करने से पहले किया जा सकता है।
FxIII

sqrt_disc की गणना कैसे की जाती है?
FxIII

क्षमा करें, FxIII मैं थोड़ा उलझन में पड़ गया होगा जब मैं अपने वैक्टरों का स्थानीयकरण कर रहा था मुझे एहसास नहीं था कि वे वैक्टर समान होंगे जब वे एक दूसरे से घटाए जाएंगे। पोस्ट करने से पहले मैं अपने कोड को थोड़ा साफ कर रहा था और मैं sqrt_disc = sqrt(disc);वापस रखना भूल गया । आपके जवाब के लिए बहुत बहुत धन्यवाद, इससे मुझे बहुत मदद मिली।
jazzdawg

जवाबों:


20

से बी तक चलने वाले सेगमेंट की गणना की जा सकती है

पी (टी) = एक + डी · टी जहां डी है बी - एक और 0 से 1 तक टी रन

अब सर्कल मूल पर केंद्रित है ( और बी को स्थानांतरित करें यदि केंद्र को मूल में रखना आवश्यक है) और त्रिज्या आर है

अगर कुछ टी के लिए आपको लगता है कि मिल आप एक चौराहे है पी की लम्बाई समान होती है आर या, समतुल्य रूप, कि की लंबाई पी चुकता के बराबर है

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

पी · पी = ( + डी · टी) · ( + डी · टी) =

एक · एक + 2 एक · डी टी + डी · डी

हम यह जानना चाहते हैं कि हमें किस P को P · P = r we मिलता है, इसलिए हम अपने आप से पूछते हैं कि कब

A · A + 2 A · D t + D · D t² = r A

या कब

D · D t · + 2 A · D t + A · A -r 0 = 0

यह बहुत प्रसिद्ध द्विघात समीकरण है

at + bt + c = 0

साथ में

ए = डी · डी ; ख = 2 एक · डी और सी = एक · एक -r²

हमें यह जांचना होगा कि क्या निर्धारक b² - 4ac धनात्मक है और इसलिए हमें t के 2 मान मिलते हैं जो हमें चौराहों के बिंदु P (t) देते हैं।

t 0 और 1 के बीच होना चाहिए अन्यथा हमें ऐसे समाधान मिले जो A और B से होकर गुजरने वाली रेखा पर स्थित हैं, लेकिन A से पहले या B के बाद हैं

[संपादित करें]

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

ए से बी तक चलने वाला सेगमेंट

डी वेक्टर है कि चाल एक बी में यदि ऐसा है तो टी 0 और 1 के बीच है, डी · टी डी का एक "उचित अंश" इतनी बात है एक + डी · में टी झूठ A_B खंड: भूरे रंग के अंक आता है जब टी है 0 और 1 और गहरे हरे रंग के बीच एक t> 1 है।

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

केंद्र के लिए घूम रहा है

अब हमारे पास एक आसान तरीका है कि जब P भिन्न होता है तो P की लंबन की गणना करता है और कहता है कि किस P के लिए वृत्त की सीमाएँ पार हैं।

उदाहरण

जैसा कि आप देखते हैं कि पी ' आर की तुलना में अधिक है, जबकि पी " आर से कम है। चूंकि वेक्टर लेन्थ और आर दोनों सकारात्मक संख्याएं हैं, इसलिए ऑर्डर के अधिक या कम होने के संबंध संरक्षित हैं। हम लेनगेट्स के बीच संबंध की गणना करते हैं। वर्ग और त्रिज्या चुकता। पी * 1 और पी * 2 कर रहे हैं का कहना है कि बनाता है | P | ² r² के बराबर

जैसा कि पूर्व-संपादन अनुभाग में उल्लेख किया गया है, हम एक द्विघात समीकरण प्राप्त करने के लिए पहुंचते हैं जहां टी हमारा चर है। जैसा कि मामले से टी रेंज के ज्ञात मूल्य मान हैं जब टी एक जटिल संख्या है - इसका मतलब है कि कोई चौराहा नहीं है; मामला जब टी दो समान समाधान हैं - इसका मतलब है कि एक चौराहा है; मामला जब दो अलग-अलग समाधान हैं- इसका मतलब है कि दो चौराहे हैं।

विभेदक पिछले हालत भेदभाव करने के लिए प्रयोग किया जाता है और एक वैधता परीक्षण टी पर किया जाता है, तो यह एक वैध चौराहे लेकिन हमारे खंड के बाहर देखने के लिए - यानी समाधान टी असली हो गया है और 0 और 1 के बीच एक उचित चौराहे कि गिरावट पर विचार किया जाएगा खंड A_B में


3
यह उपयोग करने के लिए सही एल्गोरिदम है। रियल टाइम रेंडरिंग थर्ड एडीशन , पेज 787 से 791 में यह कैसे काम करता है, इसका बहुत अच्छा विवरण। यदि आप इसे लाइब्रेरी में पा सकते हैं, तो अच्छी तरह से देख सकते हैं।
डार्सी रनर

4
इस उत्तर के लिए 8 वें उत्थान के साथ, मैं 2k प्रतिष्ठा अंक तक पहुँच गया हूँ। आपने मुझ पर जो भरोसा रखा है, उसकी मैं बहुत सराहना करता हूं। यह मेरे प्रयासों की एक मान्यता है और उच्चतम संभव गुणवत्ता उत्तर का उत्पादन करने में अपना सर्वश्रेष्ठ प्रदर्शन जारी रखने के लिए एक प्रोत्साहन है। धन्यवाद
FxIII

रुको, क्या यह दो कोने के मामलों के लिए सही है? उदाहरण के लिए, एक सर्कल t0 <= t <= t1 के बाहर लाइन द्वारा परिभाषित विमान को पार कर सकता है, लेकिन लाइन सेगमेंट के अंत बिंदुओं को थोड़ी देर बाद मारा। आपको लाइन एंड पॉइंट और सर्कल पथ के बीच न्यूनतम दूरी की जांच करने की आवश्यकता है। यदि वह दूरी सर्कल त्रिज्या से छोटी है, तो लाइन को हिट किया गया है।
डार्सी रनर

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