कैसे निर्धारित करें कि एक बिंदु 2 डी त्रिकोण में है? [बन्द है]


258

क्या यह निर्धारित करने का एक आसान तरीका है कि एक बिंदु एक त्रिकोण के अंदर है? यह 3D है, 3D नहीं है।


15
मैंने त्रिकोण परीक्षण में बिंदु के बारे में एक पूरा लेख लिखा। यह बेरिएट्रिक, पैरामीट्रिक और डॉट उत्पाद आधारित विधियों को दर्शाता है। तब यह सटीकता की समस्या से निपटता है जब एक बिंदु एक किनारे (उदाहरण के साथ) पर होता है। अंत में यह पॉइंट टू एज डिस्टेंस पर आधारित एक पूरी नई विधि को उजागर करता है। totologic.blogspot.fr/2014/01/… आनंद लें!
लॉजिक


1
यह ध्यान देने योग्य है कि यहाँ चर्चा की गई कोई भी विधि 3D स्पेस में भी मान्य है। उन्हें बस एक समन्वय परिवर्तन (और त्रिकोण के विमान पर बिंदु का एक उपयुक्त प्रक्षेपण) से पहले होने की आवश्यकता है। एक त्रिभुज 2-आयामी वस्तु है।
andreasdr

एक समाधान के लिए जो घुमावदार आदेश से स्वतंत्र है। यहाँ एक काम कर रहे बेला है: jsfiddle.net/ibowankenobi/oex3pzq2
ibrahim tanyalcin

2
मैं इस प्रश्न को बंद करने के लिए मतदान कर रहा हूं क्योंकि यह प्रोग्रामिंग के बजाय गणित के बारे में है, और राय-आधारित है (जो आपके लिए "आसान" है)।
टायलरएच

जवाबों:


264

सामान्य तौर पर, सबसे सरल (और काफी इष्टतम) एल्गोरिथ्म यह जाँच कर रहा है कि किन बिंदुओं द्वारा बनाए गए आधे-समतल के किस तरफ है।

GameDev पर इस विषय में कुछ उच्च गुणवत्ता की जानकारी दी गई है , जिसमें प्रदर्शन के मुद्दे भी शामिल हैं।

और यहां आपको आरंभ करने के लिए कुछ कोड दिए गए हैं:

float sign (fPoint p1, fPoint p2, fPoint p3)
{
    return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}

bool PointInTriangle (fPoint pt, fPoint v1, fPoint v2, fPoint v3)
{
    float d1, d2, d3;
    bool has_neg, has_pos;

    d1 = sign(pt, v1, v2);
    d2 = sign(pt, v2, v3);
    d3 = sign(pt, v3, v1);

    has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
    has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);

    return !(has_neg && has_pos);
}

12
यह आमतौर पर 2D में उपयोग किया जाता है। Barycentric निर्देशांक लोगों को भ्रमित करते हैं। इसके अलावा, त्रिभुज के कोरिडेट्स और बिंदु कॉर्डिनेट को देखते हुए, मैं बेरेंट्रिक्स का उपयोग करने की दक्षता के बारे में अनिश्चित हूं।
कोर्नेल किलीविलेज़

7
@Kornel 2 डी के रूप में अच्छी तरह से barycentric संस्करण अधिक कुशल है। आपके समाधान में यह भी समस्या है कि यह त्रिकोण के किनारों पर बिंदुओं के लिए एक अलग परिणाम की रिपोर्ट करेगा, जो कि विकर के आधार पर त्रिकोण को दक्षिणावर्त या काउंटर दक्षिणावर्त क्रम में निर्दिष्ट किया गया है।
एंड्रियास ब्रिंक

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

4
तो संकेत () फ़ंक्शन आपको बताता है कि हाफ़ प्लेन के किस तरफ (पी 2 और पी 3 के बीच की रेखा द्वारा गठित) पी 1 है?
डेविड डोरिया

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

176

निम्नलिखित समीकरण प्रणाली को हल करें:

p = p0 + (p1 - p0) * s + (p2 - p0) * t

बिंदु pअगर त्रिकोण के अंदर है 0 <= s <= 1और 0 <= t <= 1और s + t <= 1

s, tऔर बिंदु 1 - s - tके बेरेंट्रिक निर्देशांक कहलाते हैं p


1
यह आधे-प्लेन चेक की तुलना में तेज़ है, लेकिन शायद थोड़ा कठिन है अगर आप बेरिएट्रिक निर्देशांक के लिए नए हैं।
डैनियल रिकोव्स्की

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

85
मैं इसका परीक्षण करना चाहता था, इसलिए मैंने एक jsfiddle बनाया, जो @andreasdr समाधान और मैथुन संबंधी टिप्पणी पर निर्भर है: jsfiddle.net/PerroAZUL/zdaY8/1
urraka

5
अनुकूलन: s + t <= 1तात्पर्य s <= 1और t <= 1यदि s >= 0और t >= 0
थॉमस ईडिंग

7
इस लेख @ totogic.blogspot.fr/2014/01/… द्वारा प्रस्तावित @ लॉजिक पोस्ट ने मुझे इस समाधान को बेहतर ढंग से समझने में मदद की
Flayn

112

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

s = 1/(2*Area)*(p0y*p2x - p0x*p2y + (p2y - p0y)*px + (p0x - p2x)*py);
t = 1/(2*Area)*(p0x*p1y - p0y*p1x + (p0y - p1y)*px + (p1x - p0x)*py);

Areaत्रिभुज का (हस्ताक्षरित) क्षेत्र कहां है:

Area = 0.5 *(-p1y*p2x + p0y*(-p1x + p2x) + p0x*(p1y - p2y) + p1x*p2y);

बस मूल्यांकन करें s , tऔर 1-s-t। बिंदु pत्रिकोण के अंदर है अगर और केवल अगर वे सभी सकारात्मक हैं।

संपादित करें: ध्यान दें कि इस क्षेत्र के लिए उपरोक्त अभिव्यक्ति मानती है कि त्रिभुज नोड संख्या काउंटर-दक्षिणावर्त है। यदि नंबरिंग दक्षिणावर्त है, तो यह अभिव्यक्ति एक नकारात्मक क्षेत्र (लेकिन सही परिमाण के साथ) वापस कर देगी। परीक्षण ही (s>0 && t>0 && 1-s-t>0 ) नंबरिंग की दिशा पर निर्भर नहीं करता है, हालांकि, इसके बाद के संस्करण के अभिव्यक्तियों को कई गुना बढ़ा दिया जाता है 1/(2*Area)अगर त्रिकोण नोड अभिविन्यास में परिवर्तन होता है।

संपादित करें 2: एक और बेहतर कम्प्यूटेशनल दक्षता के लिए, नीचे दिए गए कॉपीराइट की टिप्पणी देखें (जो इस बात को स्पष्ट करती है कि यदि त्रिकोण नोड्स (क्लॉकवाइज या काउंटर- क्लॉकवाइज ) का ओरिएंटेशन पहले से ज्ञात है, 2*Areaतो अभिव्यक्ति के लिए विभाजन किसके द्वारा sऔर tहो सकता है बचा)। एंड्रो ब्रिंक के उत्तर के तहत टिप्पणियों में पेरो अज़ुल का jsfiddle-code भी देखें ।


6
यही कारण है कि है समीकरण प्रणाली :) सुलझाने
एंड्रियास Brinck

1
हां, मेरा कहना है कि समीकरण प्रणाली को हल करने की कम्प्यूटेशनल लागत के आधार पर आपके तरीके की कोई भी आलोचना निराधार है, क्योंकि इसे एल्गोरिथ्म के हिस्से के रूप में नहीं किया जाना है।
andreasdr

13
के माध्यम से विभाजित नहीं करके दक्षता में सुधार किया जा सकता है 2*Area, अर्थात गणना करके s´=2*|Area|*sऔर t´=2*|Area|*t(यदि बिंदुओं का उन्मुखीकरण - दक्षिणावर्त या काउंटर-क्लॉकवाइज - ज्ञात नहीं है, तो निश्चित Areaरूप से जाँच की जानी चाहिए, लेकिन अन्यथा यह भी नहीं है जांच करने की आवश्यकता है), क्योंकि s>0यह जाँच करने के लिए जाँच करने के लिए पर्याप्त है s´>0। और जाँच के बजाय 1-s-t>0यह जाँच करने के लिए पर्याप्त है s´+t´<2*|Area|
21

1
मैं जोड़ सकते हैं कि अगर p0->p1->p2है वामावर्त में कार्तीय (जो आमतौर पर है दक्षिणावर्त में स्क्रीन निर्देशांक ), Areaइस विधि द्वारा गणना सकारात्मक होंगे।
rhgb

1
@ user2600366 जब आप दिशा p0 -> p1 -> P2 -> p0 में त्रिभुज की सीमा के साथ यात्रा करते हैं, और इसी तरह, आपके पास त्रिभुज का आंतरिक भाग हमेशा आपके दाईं ओर या हमेशा आपके बाईं ओर रहेगा। पूर्व मामले में, नंबरिंग दक्षिणावर्त है, बाद वाले मामले में, यह काउंटर-क्लॉकवाइज है।
andreasdr

47

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

bool intpoint_inside_trigon(intPoint s, intPoint a, intPoint b, intPoint c)
{
    int as_x = s.x-a.x;
    int as_y = s.y-a.y;

    bool s_ab = (b.x-a.x)*as_y-(b.y-a.y)*as_x > 0;

    if((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0 == s_ab) return false;

    if((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0 != s_ab) return false;

    return true;
}

शब्दों में, यह विचार यह है: क्या बिंदु एबी या एसी दोनों रेखाओं के दाईं ओर स्थित है? अगर सच है, तो यह अंदर नहीं हो सकता। यदि गलत है, तो यह कम से कम "शंकु" के अंदर है जो स्थिति को संतुष्ट करता है। अब चूंकि हम जानते हैं कि ट्राइबॉन (त्रिकोण) के अंदर का एक बिंदु AB के समान बीसी (और सीए) के समान होना चाहिए, हम जांचते हैं कि क्या वे भिन्न हैं। यदि वे करते हैं, तो संभवतः अंदर नहीं हो सकते, अन्यथा अंदर होना चाहिए।

गणना में कुछ कीवर्ड लाइन हाफ-प्लेन और निर्धारक (2x2 क्रॉस उत्पाद) हैं। शायद एक और अधिक पांडित्यपूर्ण तरीका शायद यह सोचने के लिए है कि एक बिंदु के अंदर अगर यह एक ही तरफ (बाएं या दाएं) एबी, बीसी और सीए में से प्रत्येक के लिए है। हालांकि उपरोक्त तरीका कुछ अनुकूलन के लिए एक बेहतर फिट लग रहा था।


2
यह परीक्षण प्रदान किए गए पहले वाले की तुलना में लगभग 140-180% तेज है (धन्यवाद आप दोनों btw :)। मैंने यहाँ कोड चलाया: paste.ubuntu.com/p/k5w7ywH4p8 ऑप्टिमाइज़ेशन के साथ नोड्ज v8 इंजन का उपयोग करके अक्षम हो गया और निम्नलिखित परिणाम प्राप्त हुए: w! Np -p --minimal test1: 114.85mms test2: 64.330ms test1: 115.650ms! test2: 63.491ms test1: 117.671ms test2: 65.353ms test1: 119.146ms test2: 63.871ms test1: 118.271ms test1: 118.670ms परीक्षण 2: 63.352ms
सर्जरी)

@surgemcgee आप इसे अनुकूलन के बिना क्यों चलाएंगे? क्या तब वास्तविकता से अधिक हटाया नहीं गया है?
xuiqzy

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

33

Andreasdr और Perro Azul द्वारा पोस्ट की गई बेरेंट्रिक विधि का C # संस्करण। ध्यान दें कि यदि क्षेत्र की गणना से बचा जा सकता है sऔर tइसके विपरीत संकेत हों। मैंने पूरी तरह से इकाई परीक्षण के साथ सही व्यवहार को सत्यापित किया।

public static bool PointInTriangle(Point p, Point p0, Point p1, Point p2)
{
    var s = p0.Y * p2.X - p0.X * p2.Y + (p2.Y - p0.Y) * p.X + (p0.X - p2.X) * p.Y;
    var t = p0.X * p1.Y - p0.Y * p1.X + (p0.Y - p1.Y) * p.X + (p1.X - p0.X) * p.Y;

    if ((s < 0) != (t < 0))
        return false;

    var A = -p1.Y * p2.X + p0.Y * (p2.X - p1.X) + p0.X * (p1.Y - p2.Y) + p1.X * p2.Y;

    return A < 0 ?
            (s <= 0 && s + t >= A) :
            (s >= 0 && s + t <= A);
}

[ संपादित करें ]
@Pierre द्वारा सुझाए गए संशोधन को स्वीकार किया गया; टिप्पणी देखो


स्टेटमेंट क्लॉकवाइज और काउंटर क्लॉकवाइज ट्राइएंगल पॉइंट्स के लिए काम करता है।
ल्यूक डुपिन

@LukeDupin मुझे आपकी टिप्पणी समझ में नहीं आती। यह उत्तर 3 बिंदुओं के किसी भी आपूर्ति के लिए पोस्ट किए गए कार्य के रूप में काम करता है।
बजे ग्लेन स्लेडेन

12

बेरेंट्रिक विधि का जावा संस्करण:

class Triangle {
    Triangle(double x1, double y1, double x2, double y2, double x3,
            double y3) {
        this.x3 = x3;
        this.y3 = y3;
        y23 = y2 - y3;
        x32 = x3 - x2;
        y31 = y3 - y1;
        x13 = x1 - x3;
        det = y23 * x13 - x32 * y31;
        minD = Math.min(det, 0);
        maxD = Math.max(det, 0);
    }

    boolean contains(double x, double y) {
        double dx = x - x3;
        double dy = y - y3;
        double a = y23 * dx + x32 * dy;
        if (a < minD || a > maxD)
            return false;
        double b = y31 * dx + x13 * dy;
        if (b < minD || b > maxD)
            return false;
        double c = det - a - b;
        if (c < minD || c > maxD)
            return false;
        return true;
    }

    private final double x3, y3;
    private final double y23, x32, y31, x13;
    private final double det, minD, maxD;
}

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

यदि आप एक ही त्रिभुज के साथ विभिन्न बिंदुओं का परीक्षण करने जा रहे हैं, तो बैरियरिक संस्करण सबसे तेज़ है।

3 त्रिभुज बिंदुओं में बैरिएट्रिक संस्करण सममित नहीं है, इसलिए यह फ्लोटिंग पॉइंट राउंडिंग त्रुटियों के कारण कोर्नेल किसिएलेविक के एज हाफ-प्लेन संस्करण की तुलना में कम सुसंगत है।

साभार: मैंने उपरोक्त कोड को विकिपीडिया के लेख से बैरीकेंटिक निर्देशांक पर बनाया है।


अच्छा लगा! डेटा इनपुट को बेहतर ढंग से संभालने के लिए, javax.vecmath की पॉइंट 3 एफ / पॉइंट 2 एफ ट्यूपल्स का उपयोग करने के लिए भी इसे बेहतर बनाया जा सकता है।
एलेक्स बर्थ

10

एक सरल तरीका है:

प्रत्येक त्रिभुज के तीन कोने में बिंदु को जोड़ने वाले वैक्टर खोजें और उन वैक्टर के बीच के कोणों को योग करें। यदि कोणों का योग 2 * pi है तो बिंदु त्रिभुज के अंदर होता है।

विकल्प बताने वाले दो अच्छे स्थल हैं:

blackpawn और Wolfram


3
उम, यह विधि बिल्कुल कुशल नहीं है, और संख्यात्मक त्रुटियों के लिए बहुत संभावना है ...
कोर्नेल किसेल्विकेज़

यह काफी विपरीत है, यह बहुत अक्षम है :-) यह सिर्फ एक सरल तरीका है, हालांकि इसे लागू करना आसान है। क्या आप एक संख्यात्मक त्रुटि का एक उदाहरण दे सकते हैं जो इसका कारण होगा?
सिमोन पी स्टीवंस

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

जाँच करना कि क्या यह वास्तव में 2pi है, संख्यात्मक रूप से असंभव है, जिसे पाई का तर्कहीन बताया गया है। हालाँकि, आपको यह जांचने की आवश्यकता है कि क्या कोण पीआई से अधिक कुछ जोड़ते हैं।
lonewarrior556

10

विश्लेषणात्मक समाधान का उपयोग करके बेरेंट्रिक निर्देशांक ( एंड्रियास ब्रिंक द्वारा इंगित ) और:

  • कोष्ठक शर्तों पर गुणा का वितरण नहीं करना
  • उन्हें संग्रहीत करके कई बार समान शर्तों से बचने से
  • तुलना कम करना (जैसा कि कॉप्रोक और थॉमस ईडिंग द्वारा बताया गया है )

कोई "महंगा" संचालन की संख्या को कम कर सकता है:

function ptInTriangle(p, p0, p1, p2) {
    var dX = p.x-p2.x;
    var dY = p.y-p2.y;
    var dX21 = p2.x-p1.x;
    var dY12 = p1.y-p2.y;
    var D = dY12*(p0.x-p2.x) + dX21*(p0.y-p2.y);
    var s = dY12*dX + dX21*dY;
    var t = (p2.y-p0.y)*dX + (p0.x-p2.x)*dY;
    if (D<0) return s<=0 && t<=0 && s+t>=D;
    return s>=0 && t>=0 && s+t<=D;
}

कोड पेरो अज़ुल jsfiddle में चिपकाया जा सकता है या नीचे "रन कोड स्निपेट" पर क्लिक करके इसे आज़मा सकते हैं

var ctx = $("canvas")[0].getContext("2d");
var W = 500;
var H = 500;

var point = { x: W / 2, y: H / 2 };
var triangle = randomTriangle();

$("canvas").click(function(evt) {
    point.x = evt.pageX - $(this).offset().left;
    point.y = evt.pageY - $(this).offset().top;
    test();
});

$("canvas").dblclick(function(evt) {
    triangle = randomTriangle();
    test();
});

test();

function test() {
    var result = ptInTriangle(point, triangle.a, triangle.b, triangle.c);
    
    var info = "point = (" + point.x + "," + point.y + ")\n";
    info += "triangle.a = (" + triangle.a.x + "," + triangle.a.y + ")\n";
    info += "triangle.b = (" + triangle.b.x + "," + triangle.b.y + ")\n";
    info += "triangle.c = (" + triangle.c.x + "," + triangle.c.y + ")\n";
    info += "result = " + (result ? "true" : "false");

    $("#result").text(info);
    render();
}

function ptInTriangle(p, p0, p1, p2) {
    var A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
    var sign = A < 0 ? -1 : 1;
    var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
    var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
    
    return s > 0 && t > 0 && (s + t) < 2 * A * sign;
}

function render() {
    ctx.fillStyle = "#CCC";
    ctx.fillRect(0, 0, 500, 500);
    drawTriangle(triangle.a, triangle.b, triangle.c);
    drawPoint(point);
}

function drawTriangle(p0, p1, p2) {
    ctx.fillStyle = "#999";
    ctx.beginPath();
    ctx.moveTo(p0.x, p0.y);
    ctx.lineTo(p1.x, p1.y);
    ctx.lineTo(p2.x, p2.y);
    ctx.closePath();
    ctx.fill();
    ctx.fillStyle = "#000";
    ctx.font = "12px monospace";
    ctx.fillText("1", p0.x, p0.y);
    ctx.fillText("2", p1.x, p1.y);
    ctx.fillText("3", p2.x, p2.y);
}

function drawPoint(p) {
    ctx.fillStyle = "#F00";
    ctx.beginPath();
    ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);
    ctx.fill();
}

function rand(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomTriangle() {
    return {
        a: { x: rand(0, W), y: rand(0, H) },
        b: { x: rand(0, W), y: rand(0, H) },
        c: { x: rand(0, W), y: rand(0, H) }
    };
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<pre>Click: place the point.
Double click: random triangle.</pre>
<pre id="result"></pre>
<canvas width="500" height="500"></canvas>

के लिए अग्रणी:

  • चर "याद": 30
  • चर भंडारण: 7
  • परिवर्धन: 4
  • घटाव: 8
  • गुणन: 6
  • विभाजन: कोई नहीं
  • तुलना: ४

यह कोर्नेल किसलीलेविकेज़ समाधान (25 रिकॉल, 1 स्टोरेज, 15 सबट्रैक्शंस, 6 गुणन, 5 तुलना) के साथ काफी अच्छी तरह से तुलना करता है, और बेहतर भी हो सकता है अगर क्लॉकवाइज़ / काउंटर-क्लॉकवाइज़ डिटेक्शन की आवश्यकता हो (जो 6 रिकॉल, 1 जोड़, 2 घटाव हो) , 2 गुणन और 1 अपने आप में, विश्लेषणात्मक समाधान निर्धारक का उपयोग करते हुए, जैसा कि rhgb द्वारा बताया गया है )।


अच्छा समाधान है। मुझे लगता है कि MSE पर यहाँ मेरे पिछले दृष्टिकोण के लिए काफी समकक्ष है: math.stackexchange.com/questions/51326/…
जैक डी 'ऑरिज़ियो

मैंने अभी जैसे ही कोड का परीक्षण किया है, और यह मेरे लिए काम नहीं करता है (उदाहरण पी -4.69317198, -6.99191951 p0 -7.05846786 0.596718192 p1 -6.8703599 -2.3656591 P2 -4.69317198, -6.99191951)
Giovanni Funchal

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

1
: अपने अपने परीक्षण में सबसे तेजी से लगता है jsfiddle.net/eyal/gxw3632c/27 । सभी तरीकों के बीच का अंतर काफी छोटा है, हालांकि।
ईयाल

त्रिकोण (-1, -1), (1, -1), (0,1) और बिंदु (0, -1) का प्रयास करें। यह सही होने पर वापस लौटता है क्योंकि इसे वापस लौटना चाहिए क्योंकि s (2) + t (2)> d (2)। त्रिकोण के किनारों पर गणित के साथ कुछ गलत है, ऐसा लगता है, क्योंकि बिंदु p, p0 और p1 के बीच की सीमा पर सही है और यह <a <= <या ऐसा कुछ करने के लिए परिवर्तित करने का एक साधारण मामला नहीं है।
devnullicus

5

मैं जो करता हूं वह तीन चेहरे के मानदंडों का पूर्वव्यापी है,

  • साइड वेक्टर और चेहरे के सामान्य वेक्टर के क्रॉस उत्पाद द्वारा 3 डी में।

  • 2 डी में बस घटकों की अदला-बदली और एक की उपेक्षा करके,

तब किसी भी एक पक्ष के अंदर / बाहर तब होता है जब पक्ष का एक बिंदु उत्पाद सामान्य होता है और सदिश से बिंदु सदिश, परिवर्तन संकेत होता है। अन्य दो (या अधिक) पक्षों के लिए दोहराएं।

लाभ:

  • एक ही त्रिभुज पर कई बिंदुओं के परीक्षण के लिए बहुत कुछ बहुत बड़ा है।

  • अंदर के बिंदुओं की तुलना में अधिक बाहर के सामान्य मामले की प्रारंभिक अस्वीकृति। (यह भी कि अगर बिंदु वितरण एक तरफ भारित हो, तो पहले उस पक्ष का परीक्षण कर सकते हैं।)


5

यहाँ एक कुशल पायथन कार्यान्वयन है:

def PointInsideTriangle2(pt,tri):
    '''checks if point pt(2) is inside triangle tri(3x2). @Developer'''
    a = 1/(-tri[1,1]*tri[2,0]+tri[0,1]*(-tri[1,0]+tri[2,0])+ \
        tri[0,0]*(tri[1,1]-tri[2,1])+tri[1,0]*tri[2,1])
    s = a*(tri[2,0]*tri[0,1]-tri[0,0]*tri[2,1]+(tri[2,1]-tri[0,1])*pt[0]+ \
        (tri[0,0]-tri[2,0])*pt[1])
    if s<0: return False
    else: t = a*(tri[0,0]*tri[1,1]-tri[1,0]*tri[0,1]+(tri[0,1]-tri[1,1])*pt[0]+ \
              (tri[1,0]-tri[0,0])*pt[1])
    return ((t>0) and (1-s-t>0))

और एक उदाहरण आउटपुट:

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


मैं इस कार्य को करने में सक्षम नहीं था, उदाहरण के लिए त्रिकोण में बिंदु के लिए [(0,0), (3,0), (3,4)], न तो अंक (1,1) या (0) , 0) परीक्षण सकारात्मक। मैंने क्लॉकवाइज़ और एंटी-क्लॉकवाइज़ दोनों त्रिकोण बिंदुओं के साथ कोशिश की।
थोरसुमोनर

3

यदि आप गति की तलाश कर रहे हैं, तो यहां एक प्रक्रिया है जो आपकी मदद कर सकती है।

उनके निर्देशांकों पर त्रिभुज शीर्षों को क्रमबद्ध करें। यह सबसे खराब तीन तुलना करता है। आज्ञा देना Y0, Y1, Y2 तीन क्रमबद्ध मान हैं। उनके माध्यम से तीन क्षैतिज आरेखण करके आप विमान को दो आधे विमानों और दो स्लैब में विभाजित करते हैं। Y को क्वेरी बिंदु का संयोजक होने दें।

if Y < Y1
    if Y <= Y0 -> the point lies in the upper half plane, outside the triangle; you are done
    else Y > Y0 -> the point lies in the upper slab
else
    if Y >= Y2 -> the point lies in the lower half plane, outside the triangle; you are done
    else Y < Y2 -> the point lies in the lower slab

दो और तुलनाओं की लागत। जैसा कि आप देखते हैं, "बाउंडिंग स्लैब" के बाहर बिंदुओं के लिए त्वरित अस्वीकृति प्राप्त की जाती है।

वैकल्पिक रूप से, आप बाईं ओर और दाईं ओर ( X <= X0' or X >= X2') पर त्वरित अस्वीकृति के लिए एब्ससिस पर एक परीक्षण की आपूर्ति कर सकते हैं । यह एक ही समय में एक त्वरित बाउंडिंग बॉक्स परीक्षण को लागू करेगा, लेकिन आपको एब्ससिस पर भी छांटना होगा।

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

((X - Xi) * (Y - Yj) > (X - Xi) * (Y - Yj)) == ((X - Xi) * (Y - Yk) > (X - Xi) * (Y - Yk))

i, j, kसंयोजनों की पूरी चर्चा (उनमें से छह हैं, सॉर्ट के परिणाम के आधार पर) इस उत्तर के दायरे से बाहर है और "पाठक को एक अभ्यास के रूप में छोड़ दिया"; दक्षता के लिए, उन्हें हार्ड-कोड किया जाना चाहिए।

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

अद्यतन: एक कतरनी परिवर्तन के साथ तेजी से

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

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

फिर दिए गए "कतरनी" परिवर्तन पर विचार करें X'= X - m Y, Y' = Y, जहां उच्चतम किनारे के लिए mढलान है DX/DY। यह परिवर्तन त्रिभुज के इस पक्ष को लंबवत बना देगा। और जब से आप जानते हैं कि आप मध्य क्षैतिज के किस तरफ हैं, यह त्रिकोण के एक तरफ के संबंध में संकेत का परीक्षण करने के लिए पर्याप्त है।

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

मान लें कि आपने ढलान को पूर्वनिर्मित किया है m, साथ ही साथ X'कतरनी त्रिकोण के लिए और पक्षों के समीकरणों के गुणांक के रूप में X = m Y + p, आपको सबसे खराब स्थिति में आवश्यकता होगी

  • ऊर्ध्वाधर वर्गीकरण के लिए दो समन्वित तुलना;
  • बॉक्स अस्वीकृति के लिए वैकल्पिक रूप से एक या दो अनुपस्थित तुलना;
  • की संगणना X' = X - m Y;
  • कतरनी त्रिकोण के फोड़ा के साथ एक या दो तुलना;
  • X >< m' Y + p'कतरनी त्रिकोण के संबंधित पक्ष के खिलाफ एक साइन टेस्ट ।

3

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


3

अजगर में अन्य कार्य , डेवलपर की विधि से तेज (कम से कम मेरे लिए) और सेड्रिक ड्यूफर समाधान से प्रेरित है :

def ptInTriang(p_test, p0, p1, p2):       
     dX = p_test[0] - p0[0]
     dY = p_test[1] - p0[1]
     dX20 = p2[0] - p0[0]
     dY20 = p2[1] - p0[1]
     dX10 = p1[0] - p0[0]
     dY10 = p1[1] - p0[1]

     s_p = (dY20*dX) - (dX20*dY)
     t_p = (dX10*dY) - (dY10*dX)
     D = (dX10*dY20) - (dY10*dX20)

     if D > 0:
         return (  (s_p >= 0) and (t_p >= 0) and (s_p + t_p) <= D  )
     else:
         return (  (s_p <= 0) and (t_p <= 0) and (s_p + t_p) >= D  )

आप इसका परीक्षण कर सकते हैं:

X_size = 64
Y_size = 64
ax_x = np.arange(X_size).astype(np.float32)
ax_y = np.arange(Y_size).astype(np.float32)
coords=np.meshgrid(ax_x,ax_y)
points_unif = (coords[0].reshape(X_size*Y_size,),coords[1].reshape(X_size*Y_size,))
p_test = np.array([0 , 0])
p0 = np.array([22 , 8]) 
p1 = np.array([12 , 55]) 
p2 = np.array([7 , 19]) 
fig = plt.figure(dpi=300)
for i in range(0,X_size*Y_size):
    p_test[0] = points_unif[0][i]
    p_test[1] = points_unif[1][i]
    if ptInTriang(p_test, p0, p1, p2):
        plt.plot(p_test[0], p_test[1], '.g')
    else:
        plt.plot(p_test[0], p_test[1], '.r')

यह प्लॉट करने के लिए बहुत कुछ लेता है, लेकिन उस ग्रिड का डेवलपर के कोड के 0.0844349861145 सेकंड के मुकाबले 0.0195319652557 सेकंड में परीक्षण किया जाता है ।

अंत में कोड टिप्पणी:

# Using barycentric coordintes, any point inside can be described as:
# X = p0.x * r + p1.x * s + p2.x * t
# Y = p0.y * r + p1.y * s + p2.y * t
# with:
# r + s + t = 1  and 0 < r,s,t < 1
# then: r = 1 - s - t
# and then:
# X = p0.x * (1 - s - t) + p1.x * s + p2.x * t
# Y = p0.y * (1 - s - t) + p1.y * s + p2.y * t
#
# X = p0.x + (p1.x-p0.x) * s + (p2.x-p0.x) * t
# Y = p0.y + (p1.y-p0.y) * s + (p2.y-p0.y) * t
#
# X - p0.x = (p1.x-p0.x) * s + (p2.x-p0.x) * t
# Y - p0.y = (p1.y-p0.y) * s + (p2.y-p0.y) * t
#
# we have to solve:
#
# [ X - p0.x ] = [(p1.x-p0.x)   (p2.x-p0.x)] * [ s ]
# [ Y - p0.Y ]   [(p1.y-p0.y)   (p2.y-p0.y)]   [ t ]
#
# ---> b = A*x ; ---> x = A^-1 * b
# 
# [ s ] =   A^-1  * [ X - p0.x ]
# [ t ]             [ Y - p0.Y ]
#
# A^-1 = 1/D * adj(A)
#
# The adjugate of A:
#
# adj(A)   =   [(p2.y-p0.y)   -(p2.x-p0.x)]
#              [-(p1.y-p0.y)   (p1.x-p0.x)]
#
# The determinant of A:
#
# D = (p1.x-p0.x)*(p2.y-p0.y) - (p1.y-p0.y)*(p2.x-p0.x)
#
# Then:
#
# s_p = { (p2.y-p0.y)*(X - p0.x) - (p2.x-p0.x)*(Y - p0.Y) }
# t_p = { (p1.x-p0.x)*(Y - p0.Y) - (p1.y-p0.y)*(X - p0.x) }
#
# s = s_p / D
# t = t_p / D
#
# Recovering r:
#
# r = 1 - (s_p + t_p)/D
#
# Since we only want to know if it is insidem not the barycentric coordinate:
#
# 0 < 1 - (s_p + t_p)/D < 1
# 0 < (s_p + t_p)/D < 1
# 0 < (s_p + t_p) < D
#
# The condition is:
# if D > 0:
#     s_p > 0 and t_p > 0 and (s_p + t_p) < D
# else:
#     s_p < 0 and t_p < 0 and (s_p + t_p) > D
#
# s_p = { dY20*dX - dX20*dY }
# t_p = { dX10*dY - dY10*dX }
# D = dX10*dY20 - dY10*dX20

यह फ़ंक्शन काम नहीं कर रहा है। दे दो ptInTriang([11,45],[45, 45],[45, 45] ,[44, 45])और यह वापस आ जाएगा, trueहालांकि यह गलत है
कोड पोप

3

चूंकि कोई जेएस उत्तर नहीं है,
क्लॉकवाइज़ और काउंटर-क्लॉकवाइज़ समाधान:

function triangleContains(ax, ay, bx, by, cx, cy, x, y) {

    let det = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)

    return  det * ((bx - ax) * (y - ay) - (by - ay) * (x - ax)) > 0 &&
            det * ((cx - bx) * (y - by) - (cy - by) * (x - bx)) > 0 &&
            det * ((ax - cx) * (y - cy) - (ay - cy) * (x - cx)) > 0 

}

EDIT: डिट गणना के लिए एक टाइपो था ( cy - ayइसके बजाय cx - ax), यह तय है।

https://jsfiddle.net/jniac/rctb3gfL/

function triangleContains(ax, ay, bx, by, cx, cy, x, y) {

    let det = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)
	
    return  det * ((bx - ax) * (y - ay) - (by - ay) * (x - ax)) > 0 &&
            det * ((cx - bx) * (y - by) - (cy - by) * (x - bx)) > 0 &&
            det * ((ax - cx) * (y - cy) - (ay - cy) * (x - cx)) > 0 

}






let width = 500, height = 500

// clockwise
let triangle1 = {

	A : { x: 10, y: -10 },
	C : { x: 20, y: 100 },
	B : { x: -90, y: 10 },
	
	color: '#f00',

}

// counter clockwise
let triangle2 = {

	A : { x: 20, y: -60 },
	B : { x: 90, y: 20 },
	C : { x: 20, y: 60 },

	color: '#00f',
	
}


let scale = 2
let mouse = { x: 0, y: 0 }






// DRAW >

let wrapper = document.querySelector('div.wrapper')

wrapper.onmousemove = ({ layerX:x, layerY:y }) => {
	
	x -= width / 2
	y -= height / 2
	x /= scale
	y /= scale
	
	mouse.x = x
	mouse.y = y
	
	drawInteractive()

}

function drawArrow(ctx, A, B) {

	let v = normalize(sub(B, A), 3)
	let I = center(A, B)
	
	let p
	
	p = add(I, rotate(v, 90), v)
	ctx.moveTo(p.x, p.y)
	ctx.lineTo(I.x, I .y)
	p = add(I, rotate(v, -90), v)
	ctx.lineTo(p.x, p.y)

}

function drawTriangle(ctx, { A, B, C, color }) {

	ctx.beginPath()
	ctx.moveTo(A.x, A.y)
	ctx.lineTo(B.x, B.y)
	ctx.lineTo(C.x, C.y)
	ctx.closePath()
	
	ctx.fillStyle = color + '6'
	ctx.strokeStyle = color
	ctx.fill()
	
	drawArrow(ctx, A, B)
	drawArrow(ctx, B, C)
	drawArrow(ctx, C, A)
	
	ctx.stroke()

}

function contains({ A, B, C }, P) {

	return triangleContains(A.x, A.y, B.x, B.y, C.x, C.y, P.x, P.y)

}

function resetCanvas(canvas) {

	canvas.width = width
	canvas.height = height
	
	let ctx = canvas.getContext('2d')

	ctx.resetTransform()
	ctx.clearRect(0, 0, width, height)
	ctx.setTransform(scale, 0, 0, scale, width/2, height/2)
	
}

function drawDots() {

	let canvas = document.querySelector('canvas#dots')
	let ctx = canvas.getContext('2d')

	resetCanvas(canvas)
	
	let count = 1000

	for (let i = 0; i < count; i++) {

		let x = width * (Math.random() - .5)
		let y = width * (Math.random() - .5)
		
		ctx.beginPath()
		ctx.ellipse(x, y, 1, 1, 0, 0, 2 * Math.PI)
		
		if (contains(triangle1, { x, y })) {
		
			ctx.fillStyle = '#f00'
		
		} else if (contains(triangle2, { x, y })) {
		
			ctx.fillStyle = '#00f'
		
		} else {
		
			ctx.fillStyle = '#0003'
		
		}

		
		ctx.fill()
		
	}
	
}

function drawInteractive() {

	let canvas = document.querySelector('canvas#interactive')
	let ctx = canvas.getContext('2d')

	resetCanvas(canvas)
	
	ctx.beginPath()
	ctx.moveTo(0, -height/2)
	ctx.lineTo(0, height/2)
	ctx.moveTo(-width/2, 0)
	ctx.lineTo(width/2, 0)
	ctx.strokeStyle = '#0003'
	ctx.stroke()
	
	drawTriangle(ctx, triangle1)
	drawTriangle(ctx, triangle2)
	
	ctx.beginPath()
	ctx.ellipse(mouse.x, mouse.y, 4, 4, 0, 0, 2 * Math.PI)
	
	if (contains(triangle1, mouse)) {
	
		ctx.fillStyle = triangle1.color + 'a'
		ctx.fill()
		
	} else if (contains(triangle2, mouse)) {
	
		ctx.fillStyle = triangle2.color + 'a'
		ctx.fill()
		
	} else {
	
		ctx.strokeStyle = 'black'
		ctx.stroke()
		
	}
	
}

drawDots()
drawInteractive()










// trigo

function add(...points) {
	
	let x = 0, y = 0
	
	for (let point of points) {
	
		x += point.x
		y += point.y
	
	}
	
	return { x, y }

}

function center(...points) {
	
	let x = 0, y = 0
	
	for (let point of points) {
	
		x += point.x
		y += point.y
	
	}
	
	x /= points.length
	y /= points.length
	
	return { x, y }

}

function sub(A, B) {

	let x = A.x - B.x
	let y = A.y - B.y
	
	return { x, y }

}

function normalize({ x, y }, length = 10) {

	let r = length / Math.sqrt(x * x + y * y)
	
	x *= r
	y *= r
	
	return { x, y }

}

function rotate({ x, y }, angle = 90) {

	let length = Math.sqrt(x * x + y * y)
	
	angle *= Math.PI / 180
	angle += Math.atan2(y, x)
	
	x = length * Math.cos(angle)
	y = length * Math.sin(angle)
	
	return { x, y }

}
* {
	margin: 0;
}

html {
	font-family: monospace;
}

body {
	padding: 32px;
}

span.red {
	color: #f00;
}

span.blue {
	color: #00f;
}

canvas {
	position: absolute;
	border: solid 1px #ddd;
}
<p><span class="red">red triangle</span> is clockwise</p>
<p><span class="blue">blue triangle</span> is couter clockwise</p>
<br>
<div class="wrapper">
	<canvas id="dots"></canvas>
	<canvas id="interactive"></canvas>
</div>

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

मैं यहाँ उसी विधि का उपयोग कर रहा हूँ जैसा कि ऊपर वर्णित है: एक बिंदु एबीसी के अंदर है यदि यह क्रमशः प्रत्येक पंक्ति एबी, बीसी, सीए के "समान" पक्ष पर है।

त्रिकोण समावेश उदाहरण


मैंने इस कोड को थका दिया और यह काम नहीं कर रहा है। यह हमेशा झूठा लौटता है।
xApple

हम्म् ... आपने शायद गलती की है। यहाँ उस फंक्शन के साथ एक फीलिंग चल रही है: jsfiddle.net/jniac/rctb3gfL
जोसेफ मर्डरिग्नैक

मैंने आपकी पायथन प्रतिक्रिया देखी है, हम एक ही विधि का उपयोग कर रहे हैं, अगर मैं एक और लाइन ( let det = (bx - ax) * (cy - ay) - (by - ay) * (cy - ay)) का उपयोग करता हूं, तो यह त्रिकोण वाइंडिंग क्रम निर्धारित करना है, इसलिए विधि CW & CCW त्रिकोण के साथ काम करेगी (देखें jsFiddle)।
जोसेफ मेरिडिग्नैक

1
एचएम मैंने एक गलती की, मैंने लिखा: let det = (bx - ax) * (cy - ay) - (by - ay) * (cy - ay)इसके बजाय let det = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)यह तय हो गया है, रिपोर्टिंग के लिए धन्यवाद
यूसुफ मर्डीग्नैक

2

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

  1. क्षेत्र A को s * v02 + t * v01 द्वारा दिए गए किसी भी वेक्टर के रूप में परिभाषित किया गया है, शर्त s> = 0 और t> के साथ = 0. यदि त्रिकोण v0, v1, v2 के अंदर कोई बिंदु है, तो यह क्षेत्र A के अंदर होना चाहिए।

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

  1. यदि आगे एस प्रतिबंधित है, और टी [0, 1] से संबंधित है। हमें एरिया B मिलता है जिसमें s * v02 + t * v01 के सभी वैक्टर होते हैं, जिनमें s, t की संख्या 0, 1] से होती है। यह ध्यान देने योग्य है कि एरिया बी का निचला हिस्सा त्रिभुज v0, v1, v2 का दर्पण है। समस्या यह है कि अगर हम एरिया बी के निचले हिस्से को छोड़कर, आगे की कुछ शर्तों को दे सकते हैं।

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

  1. मान लें कि हम एक मान देते हैं, और t [0, 1] में बदल रहा है। निम्नलिखित तस्वीर में, बिंदु p v1v2 के किनारे पर है। S * v02 + t * v01 के सभी वैक्टर जो साधारण वेक्टर राशि द्वारा डैश लाइन के साथ हैं। V1v2 और डैश लाइन क्रॉस पॉइंट p पर, हमारे पास:

(१-एस) | v0v2 | / | v0v2 | = tp | v0v1 | / | v0v1 |

हमें 1 - s = tp मिलता है, फिर 1 = s + tp मिलता है। यदि कोई t> tp, जो 1 <s + t जहां डबल डैश लाइन पर है, तो वेक्टर त्रिभुज के बाहर है, कोई भी t <= tp, जो 1> = s + t जहां एकल डैश लाइन पर है, वेक्टर है त्रिकोण के अंदर।

फिर अगर हमने किसी भी s को [0, 1] में दिया है, तो संबंधित t को 1> = s + t से मिलना चाहिए, त्रिकोण के अंदर वेक्टर के लिए।

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

तो अंत में हम v = s * v02 + t * v01 प्राप्त करते हैं, v स्थिति s, t, s + t के साथ त्रिकोण के अंदर है [0, 1] से संबंधित है। फिर अनुवाद करने के लिए, हमारे पास है

p - p0 = s * (p1 - p0) + t * (P2 - p0) s, t, s + t के साथ [0, 1] में

जो समीकरण प्रणाली p = p0 + s * (p1 - p0) + t * (P2 - p0) को s, t, s + t के साथ [0, 1] से जोड़ने के लिए एंड्रियास के समाधान के समान है।


आप बस यह कह सकते हैं कि आप तीनों कोणों द्वारा परिभाषित स्थानीय फ्रेम का उपयोग करते हैं ताकि पक्ष s = 0, t = 0 और s + t = 1 हो जाएं। Affine समन्वय परिवर्तन रैखिक बीजगणित का एक प्रसिद्ध ऑपरेशन है।
यवेस डाएव

2

यहां अजगर में एक समाधान है जो कुशल है, प्रलेखित है और तीन unittests शामिल हैं। यह पेशेवर-ग्रेड गुणवत्ता है और एक मॉड्यूल के रूप में आपकी परियोजना में उतारने के लिए तैयार है।

import unittest

###############################################################################
def point_in_triangle(point, triangle):
    """Returns True if the point is inside the triangle
    and returns False if it falls outside.
    - The argument *point* is a tuple with two elements
    containing the X,Y coordinates respectively.
    - The argument *triangle* is a tuple with three elements each
    element consisting of a tuple of X,Y coordinates.

    It works like this:
    Walk clockwise or counterclockwise around the triangle
    and project the point onto the segment we are crossing
    by using the dot product.
    Finally, check that the vector created is on the same side
    for each of the triangle's segments.
    """
    # Unpack arguments
    x, y = point
    ax, ay = triangle[0]
    bx, by = triangle[1]
    cx, cy = triangle[2]
    # Segment A to B
    side_1 = (x - bx) * (ay - by) - (ax - bx) * (y - by)
    # Segment B to C
    side_2 = (x - cx) * (by - cy) - (bx - cx) * (y - cy)
    # Segment C to A
    side_3 = (x - ax) * (cy - ay) - (cx - ax) * (y - ay)
    # All the signs must be positive or all negative
    return (side_1 < 0.0) == (side_2 < 0.0) == (side_3 < 0.0)

###############################################################################
class TestPointInTriangle(unittest.TestCase):

    triangle = ((22 , 8),
                (12 , 55),
                (7 , 19))

    def test_inside(self):
        point = (15, 20)
        self.assertTrue(point_in_triangle(point, self.triangle))

    def test_outside(self):
        point = (1, 7)
        self.assertFalse(point_in_triangle(point, self.triangle))

    def test_border_case(self):
        """If the point is exactly on one of the triangle's edges,
        we consider it is inside."""
        point = (7, 19)
        self.assertTrue(point_in_triangle(point, self.triangle))

###############################################################################
if __name__ == "__main__":
    suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestPointInTriangle)
    unittest.TextTestRunner().run(suite)

इसकी वैधता की पुष्टि करने के लिए ऊपर एल्गोरिथ्म के लिए एक अतिरिक्त वैकल्पिक ग्राफिकल परीक्षण है:

import random
from matplotlib import pyplot
from triangle_test import point_in_triangle

###############################################################################
# The area #
size_x = 64
size_y = 64

# The triangle #
triangle = ((22 , 8),
            (12 , 55),
            (7 , 19))

# Number of random points #
count_points = 10000

# Prepare the figure #
figure = pyplot.figure()
axes = figure.add_subplot(111, aspect='equal')
axes.set_title("Test the 'point_in_triangle' function")
axes.set_xlim(0, size_x)
axes.set_ylim(0, size_y)

# Plot the triangle #
from matplotlib.patches import Polygon
axes.add_patch(Polygon(triangle, linewidth=1, edgecolor='k', facecolor='none'))

# Plot the points #
for i in range(count_points):
    x = random.uniform(0, size_x)
    y = random.uniform(0, size_y)
    if point_in_triangle((x,y), triangle): pyplot.plot(x, y, '.g')
    else:                                  pyplot.plot(x, y, '.b')

# Save it #
figure.savefig("point_in_triangle.pdf")

निम्नलिखित ग्राफिक का निर्माण:

Point_in_triangle फ़ंक्शन का परीक्षण करें


1

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

यदि वह रेखा जिस पर बिंदु स्थित क्षैतिज है, ऊपर / नीचे का उपयोग करें।

यदि बिंदु कई त्रिभुजों के सामान्य शीर्ष पर है, तो त्रिकोण का उपयोग करें जिसके केंद्र के साथ बिंदु सबसे छोटा कोण बनाता है।

अधिक मज़ा: तीन बिंदु एक सीधी रेखा (शून्य डिग्री) में हो सकते हैं, उदाहरण के लिए (0,0) - (0,10) - (0,5)। एक त्रिकोणीय एल्गोरिथ्म में, "कान" (0,10) को काट दिया जाना चाहिए, "त्रिकोण" एक सीधी रेखा के पतित मामले के रूप में उत्पन्न होता है।


1

यह निर्धारित करने के लिए सबसे सरल अवधारणा है कि एक बिंदु त्रिकोण के अंदर या बाहर है या त्रिकोण के एक हाथ पर।

एक बिंदु का निर्धारण निर्धारकों द्वारा एक त्रिभुज के अंदर होता है:

एक बिंदु का निर्धारण निर्धारकों द्वारा एक त्रिभुज के अंदर होता है

सबसे सरल काम कोड:

#-*- coding: utf-8 -*-

import numpy as np

tri_points = [(1,1),(2,3),(3,1)]

def pisinTri(point,tri_points):
    Dx , Dy = point

    A,B,C = tri_points
    Ax, Ay = A
    Bx, By = B
    Cx, Cy = C

    M1 = np.array([ [Dx - Bx, Dy - By, 0],
                    [Ax - Bx, Ay - By, 0],
                    [1      , 1      , 1]
                  ])

    M2 = np.array([ [Dx - Ax, Dy - Ay, 0],
                    [Cx - Ax, Cy - Ay, 0],
                    [1      , 1      , 1]
                  ])

    M3 = np.array([ [Dx - Cx, Dy - Cy, 0],
                    [Bx - Cx, By - Cy, 0],
                    [1      , 1      , 1]
                  ])

    M1 = np.linalg.det(M1)
    M2 = np.linalg.det(M2)
    M3 = np.linalg.det(M3)
    print(M1,M2,M3)

    if(M1 == 0 or M2 == 0 or M3 ==0):
            print("Point: ",point," lies on the arms of Triangle")
    elif((M1 > 0 and M2 > 0 and M3 > 0)or(M1 < 0 and M2 < 0 and M3 < 0)):
            #if products is non 0 check if all of their sign is same
            print("Point: ",point," lies inside the Triangle")
    else:
            print("Point: ",point," lies outside the Triangle")

print("Vertices of Triangle: ",tri_points)
points = [(0,0),(1,1),(2,3),(3,1),(2,2),(4,4),(1,0),(0,4)]
for c in points:
    pisinTri(c,tri_points)

0

सबसे आसान तरीका और यह सभी प्रकार के त्रिकोणों के साथ काम करता है, बस P बिंदु A, B, C बिंदु कोणों के कोणों का निर्धारण करता है। यदि कोणों में से कोई भी 180.0 डिग्री से बड़ा है, तो यह बाहर है, अगर 180.0 तो यह परिधि पर है और यदि एसीओस आपको धोखा दे रहा है और 180.0 से कम है, तो यह अंदर है। http: // गणित-भौतिकी को समझने के लिए एक नज़र डालें। -psychology.blogspot.hu/2015/01/earlish-determination-that-point-is.html


0

ईमानदारी से यह साइमन पी स्टीवन के जवाब के रूप में सरल है, लेकिन उस दृष्टिकोण के साथ आपके पास इस बात पर ठोस नियंत्रण नहीं है कि आप त्रिकोण के किनारों पर बिंदुओं को शामिल करना चाहते हैं या नहीं।

मेरा दृष्टिकोण थोड़ा अलग है लेकिन बहुत बुनियादी है। निम्नलिखित त्रिकोण पर विचार करें;

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

त्रिभुज में बिंदु होने के लिए हमें 3 स्थितियों को पूरा करना होगा

  1. ACE कोण (हरा) ACB कोण (लाल) से छोटा होना चाहिए
  2. ECB कोण (नीला) ACB कोण (लाल) से छोटा होना चाहिए
  3. बिंदु E और पॉइंट C शॉड का एक ही चिन्ह होता है जब उनके x और y मान को समीकरण के लिए लागू किया जाता है | AB | लाइन।

इस पद्धति में आपको व्यक्तिगत रूप से किनारों पर बिंदु को शामिल करने या बाहर करने का पूर्ण नियंत्रण है। तो आप जाँच सकते हैं कि क्या कोई बिंदु त्रिभुज में है जिसमें केवल AC | AC | उदाहरण के लिए किनारे।

तो जावास्क्रिप्ट में मेरा समाधान इस प्रकार होगा;

function isInTriangle(t,p){

  function isInBorder(a,b,c,p){
    var m = (a.y - b.y) / (a.x - b.x);                     // calculate the slope
    return Math.sign(p.y - m*p.x + m*a.x - a.y) === Math.sign(c.y - m*c.x + m*a.x - a.y);
  }
  
  function findAngle(a,b,c){                               // calculate the C angle from 3 points.
    var ca = Math.hypot(c.x-a.x, c.y-a.y),                 // ca edge length
        cb = Math.hypot(c.x-b.x, c.y-b.y),                 // cb edge length
        ab = Math.hypot(a.x-b.x, a.y-b.y);                 // ab edge length
    return Math.acos((ca*ca + cb*cb - ab*ab) / (2*ca*cb)); // return the C angle
  }

  var pas = t.slice(1)
             .map(tp => findAngle(p,tp,t[0])),             // find the angle between (p,t[0]) with (t[1],t[0]) & (t[2],t[0])
       ta = findAngle(t[1],t[2],t[0]);
  return pas[0] < ta && pas[1] < ta && isInBorder(t[1],t[2],t[0],p);
}

var triangle = [{x:3, y:4},{x:10, y:8},{x:6, y:10}],
      point1 = {x:3, y:9},
      point2 = {x:7, y:9};

console.log(isInTriangle(triangle,point1));
console.log(isInTriangle(triangle,point2));


0
bool isInside( float x, float y, float x1, float y1, float x2, float y2, float x3, float y3 ) {
  float l1 = (x-x1)*(y3-y1) - (x3-x1)*(y-y1), 
    l2 = (x-x2)*(y1-y2) - (x1-x2)*(y-y2), 
    l3 = (x-x3)*(y2-y3) - (x2-x3)*(y-y3);
  return (l1>0 && l2>0  && l3>0) || (l1<0 && l2<0 && l3<0);
}

यह इससे अधिक कुशल नहीं हो सकता है! एक त्रिभुज के प्रत्येक पक्ष में स्वतंत्र स्थिति और अभिविन्यास हो सकता है, इसलिए तीन गणनाएं: एल 1, एल 2 और एल 3 को निश्चित रूप से प्रत्येक में 2 गुणा शामिल करने की आवश्यकता होती है। एक बार जब एल 1, एल 2 और एल 3 ज्ञात हो जाते हैं, तो परिणाम कुछ बुनियादी तुलना और बूलियन ऑपरेशन से दूर है।


0

मान लिया गया कि उच्च-प्रदर्शन कोड जिसे मैंने जावास्क्रिप्ट में अनुकूलित किया है (नीचे लेख):

function pointInTriangle (p, p0, p1, p2) {
  return (((p1.y - p0.y) * (p.x - p0.x) - (p1.x - p0.x) * (p.y - p0.y)) | ((p2.y - p1.y) * (p.x - p1.x) - (p2.x - p1.x) * (p.y - p1.y)) | ((p0.y - p2.y) * (p.x - p2.x) - (p0.x - p2.x) * (p.y - p2.y))) >= 0;
}
  • pointInTriangle(p, p0, p1, p2) - काउंटर-क्लॉकवाइज त्रिकोण के लिए
  • pointInTriangle(p, p0, p1, p2) - दक्षिणावर्त त्रिकोण के लिए

में देखो jsFiddle (प्रदर्शन परीक्षण शामिल है), वहाँ भी एक अलग समारोह में जाँच घुमावदार है। या नीचे "रन कोड स्निपेट" दबाएं

var ctx = $("canvas")[0].getContext("2d");
var W = 500;
var H = 500;

var point = { x: W / 2, y: H / 2 };
var triangle = randomTriangle();

$("canvas").click(function(evt) {
    point.x = evt.pageX - $(this).offset().left;
    point.y = evt.pageY - $(this).offset().top;
    test();
});

$("canvas").dblclick(function(evt) {
    triangle = randomTriangle();
    test();
});

document.querySelector('#performance').addEventListener('click', _testPerformance);

test();

function test() {
    var result = checkClockwise(triangle.a, triangle.b, triangle.c) ? pointInTriangle(point, triangle.a, triangle.c, triangle.b) : pointInTriangle(point, triangle.a, triangle.b, triangle.c);
    
    var info = "point = (" + point.x + "," + point.y + ")\n";
    info += "triangle.a = (" + triangle.a.x + "," + triangle.a.y + ")\n";
    info += "triangle.b = (" + triangle.b.x + "," + triangle.b.y + ")\n";
    info += "triangle.c = (" + triangle.c.x + "," + triangle.c.y + ")\n";
    info += "result = " + (result ? "true" : "false");

    $("#result").text(info);
    render();
}

function _testPerformance () {
	var px = [], py = [], p0x = [], p0y = [], p1x = [], p1y = [], p2x = [], p2y = [], p = [], p0 = [], p1 = [], p2 = [];
    
	for(var i = 0; i < 1000000; i++) {
    p[i] = {x: Math.random() * 100, y: Math.random() * 100};
    p0[i] = {x: Math.random() * 100, y: Math.random() * 100};
    p1[i] = {x: Math.random() * 100, y: Math.random() * 100};
    p2[i] = {x: Math.random() * 100, y: Math.random() * 100};
  }
  console.time('optimal: pointInTriangle');
  for(var i = 0; i < 1000000; i++) {
    pointInTriangle(p[i], p0[i], p1[i], p2[i]);
  }
  console.timeEnd('optimal: pointInTriangle');

  console.time('original: ptInTriangle');
  for(var i = 0; i < 1000000; i++) {
  	ptInTriangle(p[i], p0[i], p1[i], p2[i]);
  }
  console.timeEnd('original: ptInTriangle');
}

function pointInTriangle (p, p0, p1, p2) {
	return (((p1.y - p0.y) * (p.x - p0.x) - (p1.x - p0.x) * (p.y - p0.y)) | ((p2.y - p1.y) * (p.x - p1.x) - (p2.x - p1.x) * (p.y - p1.y)) | ((p0.y - p2.y) * (p.x - p2.x) - (p0.x - p2.x) * (p.y - p2.y))) >= 0;
}

function ptInTriangle(p, p0, p1, p2) {
    var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y);
    var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y);

    if (s <= 0 || t <= 0) return false;

    var A = (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
    return (s + t) < A;
}

function render() {
    ctx.fillStyle = "#CCC";
    ctx.fillRect(0, 0, 500, 500);
    drawTriangle(triangle.a, triangle.b, triangle.c);
    drawPoint(point);
}

function checkClockwise(p0, p1, p2) {
    var A = (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
    return A > 0;
}

function drawTriangle(p0, p1, p2) {
    ctx.fillStyle = "#999";
    ctx.beginPath();
    ctx.moveTo(p0.x, p0.y);
    ctx.lineTo(p1.x, p1.y);
    ctx.lineTo(p2.x, p2.y);
    ctx.closePath();
    ctx.fill();
    ctx.fillStyle = "#000";
    ctx.font = "12px monospace";
    ctx.fillText("1", p0.x, p0.y);
    ctx.fillText("2", p1.x, p1.y);
    ctx.fillText("3", p2.x, p2.y);
}

function drawPoint(p) {
    ctx.fillStyle = "#F00";
    ctx.beginPath();
    ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);
    ctx.fill();
}

function rand(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomTriangle() {
    return {
        a: { x: rand(0, W), y: rand(0, H) },
        b: { x: rand(0, W), y: rand(0, H) },
        c: { x: rand(0, W), y: rand(0, H) }
    };
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="performance">Run performance test (open console)</button>
<pre>Click: place the point.
Double click: random triangle.</pre>
<pre id="result"></pre>
<canvas width="500" height="500"></canvas>

इससे प्रेरित: http://www.phatcode.net/articles.php?id=459


-1
bool point2Dtriangle(double e,double f, double a,double b,double c, double g,double h,double i, double v, double w){
    /* inputs: e=point.x, f=point.y
               a=triangle.Ax, b=triangle.Bx, c=triangle.Cx 
               g=triangle.Ay, h=triangle.By, i=triangle.Cy */
    v = 1 - (f * (b - c) + h * (c - e) + i * (e - b)) / (g * (b - c) + h * (c - a) + i * (a - b));
    w = (f * (a - b) + g * (b - e) + h * (e - a)) / (g * (b - c) + h * (c - a) + i * (a - b));
    if (*v > -0.0 && *v < 1.0000001 && *w > -0.0 && *w < *v) return true;//is inside
    else return false;//is outside
    return 0;
} 

बेरेंट्रिक से परिवर्तित लगभग सही कार्टेशियन निर्देशांक * v (x) और * w (y) डबल्स के भीतर निर्यात किए जाते हैं। दोनों निर्यात युगल में प्रत्येक मामले में पहले एक * चार होना चाहिए, संभावना: * v और * w कोड का उपयोग एक चतुष्कोण के दूसरे त्रिकोण के लिए भी किया जा सकता है। इसके द्वारा हस्ताक्षरित केवल दक्षिणावर्त abcd क्वाड से त्रिभुज abc लिखा है।

A---B
|..\\.o|  
|....\\.| 
D---C 

o बिंदु दूसरे त्रिभुज के साथ परीक्षण के लिए ABC त्रिभुज के अंदर है, इस फ़ंक्शन को CDA दिशा कहते हैं, और परिणाम चतुर्भुज के बाद *v=1-*v;और उसके *w=1-*w;लिए सही होना चाहिए


-1

मुझे "नियंत्रण योग्य वातावरण" में त्रिकोण चेक में बिंदु की आवश्यकता होती है, जब आप पूरी तरह से सुनिश्चित हो जाते हैं कि त्रिकोण दक्षिणावर्त होंगे। इसलिए, मैंने पेरो अज़ुल की jsfiddle को लिया और इसे ऐसे मामलों के लिए कॉप्रोक द्वारा सुझाए अनुसार संशोधित किया ; निरर्थक 0.5 और 2 गुणा को भी हटा दिया क्योंकि वे एक दूसरे को रद्द कर रहे हैं।

http://jsfiddle.net/dog_funtom/H7D7g/

var ctx = $("canvas")[0].getContext("2d");
var W = 500;
var H = 500;

var point = {
    x: W / 2,
    y: H / 2
};
var triangle = randomTriangle();

$("canvas").click(function (evt) {
    point.x = evt.pageX - $(this).offset().left;
    point.y = evt.pageY - $(this).offset().top;
    test();
});

$("canvas").dblclick(function (evt) {
    triangle = randomTriangle();
    test();
});

test();

function test() {
    var result = ptInTriangle(point, triangle.a, triangle.b, triangle.c);

    var info = "point = (" + point.x + "," + point.y + ")\n";
    info += "triangle.a = (" + triangle.a.x + "," + triangle.a.y + ")\n";
    info += "triangle.b = (" + triangle.b.x + "," + triangle.b.y + ")\n";
    info += "triangle.c = (" + triangle.c.x + "," + triangle.c.y + ")\n";
    info += "result = " + (result ? "true" : "false");

    $("#result").text(info);
    render();
}

function ptInTriangle(p, p0, p1, p2) {
    var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y);
    var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y);

    if (s <= 0 || t <= 0) return false;

    var A = (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);

    return (s + t) < A;
}

function checkClockwise(p0, p1, p2) {
    var A = (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
    return A > 0;
}

function render() {
    ctx.fillStyle = "#CCC";
    ctx.fillRect(0, 0, 500, 500);
    drawTriangle(triangle.a, triangle.b, triangle.c);
    drawPoint(point);
}

function drawTriangle(p0, p1, p2) {
    ctx.fillStyle = "#999";
    ctx.beginPath();
    ctx.moveTo(p0.x, p0.y);
    ctx.lineTo(p1.x, p1.y);
    ctx.lineTo(p2.x, p2.y);
    ctx.closePath();
    ctx.fill();
    ctx.fillStyle = "#000";
    ctx.font = "12px monospace";
    ctx.fillText("1", p0.x, p0.y);
    ctx.fillText("2", p1.x, p1.y);
    ctx.fillText("3", p2.x, p2.y);
}

function drawPoint(p) {
    ctx.fillStyle = "#F00";
    ctx.beginPath();
    ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);
    ctx.fill();
}

function rand(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomTriangle() {
    while (true) {
        var result = {
            a: {
                x: rand(0, W),
                y: rand(0, H)
            },
            b: {
                x: rand(0, W),
                y: rand(0, H)
            },
            c: {
                x: rand(0, W),
                y: rand(0, H)
            }
        };
        if (checkClockwise(result.a, result.b, result.c)) return result;
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<pre>Click: place the point.
Double click: random triangle.</pre>

<pre id="result"></pre>

<canvas width="500" height="500"></canvas>

यहां एकता के लिए समान C # कोड है:

public static bool IsPointInClockwiseTriangle(Vector2 p, Vector2 p0, Vector2 p1, Vector2 p2)
{
    var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y);
    var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y);

    if (s <= 0 || t <= 0)
        return false;

    var A = (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);

    return (s + t) < A;
}

-3

यह जांचने के सबसे आसान तरीकों में से एक है कि त्रिभुज (एक्स 1, वाई 1), (एक्स 2, वाई 2), (एक्स 3, वाई 3) के कोने से बना क्षेत्र सकारात्मक है या नहीं।

क्षेत्र सूत्र द्वारा गणना की जा सकती है:

1/2 [X1 (y2-y3) + x2 (y3 – y1) + x3 (y1 – y2)]

या अजगर कोड के रूप में लिखा जा सकता है:

def triangleornot(p1,p2,p3):
    return (1/ 2) [p1[0](p2[1]–p3[1]) + p2[0] (p3[1]–p1[1]) + p3[0] (p1[0]–p2[0])]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.