কোনও বিন্দু 2D ত্রিভুজের মধ্যে রয়েছে কিনা তা কীভাবে নির্ধারণ করবেন? [বন্ধ]


258

কোনও বিন্দু ত্রিভুজের অভ্যন্তরে রয়েছে কিনা তা নির্ধারণের জন্য কি সহজ উপায় আছে? এটি 2 ডি, 3 ডি নয়।


15
আমি ত্রিভুজ পরীক্ষায় পয়েন্ট সম্পর্কে একটি সম্পূর্ণ নিবন্ধ লিখেছিলাম। এটি বারিসেন্ট্রিক, প্যারামিট্রিক এবং ডট পণ্য ভিত্তিক পদ্ধতিগুলি দেখায়। তারপরে এটি সঠিকভাবে সমস্যা দেখা দেয় যখন কোনও বিন্দু ঠিক এক কিনারে থাকে (উদাহরণ সহ)। অবশেষে এটি বিন্দু থেকে প্রান্ত দূরত্বের উপর ভিত্তি করে একটি সম্পূর্ণ নতুন পদ্ধতি প্রকাশ করে। টোটোলজিক.ব্লগস্পট.ফ্র / ২০১৪ / ২০১৮ / উপভোগ করুন!
লজিক


1
এখানে লক্ষণীয় যে এখানে আলোচনা করা কোনও পদ্ধতি 3 ডি স্পেসেও বৈধ। তাদের কেবল একটি সমন্বিত রূপান্তর (এবং ত্রিভুজটির সমতলের বিন্দুর যথাযথ অভিক্ষেপ) এর আগে হওয়া দরকার। একটি ত্রিভুজ একটি 2-মাত্রিক বস্তু।
andreasdr

একটি সমাধানের জন্য যা ঘুরানোর আদেশের থেকে পৃথক। এখানে একটি কার্যক্ষম ফিডল রয়েছে: jsfiddle.net/ibowankenobi/oex3pzq2
ইব্রাহিম ট্যানিয়েলসিন

2
আমি এই প্রশ্নটি বন্ধ করার জন্য ভোট দিচ্ছি কারণ এটি প্রোগ্রামিংয়ের চেয়ে গণিত সম্পর্কে, এবং মতামত ভিত্তিক (আপনার কাছে "সহজ" কী?)।
টাইলারহহ

উত্তর:


264

সাধারণভাবে, সরল (এবং বেশ অনুকূল) অ্যালগরিদমটি বিন্দুটি প্রান্তগুলি দ্বারা তৈরি অর্ধ-বিমানের কোন দিকে পরীক্ষা করছে।

পারফরম্যান্সের সমস্যাগুলি সহ গেমডেভে এই বিষয়টিতে কিছু উচ্চ মানের তথ্য দেওয়া আছে ।

আপনাকে শুরু করার জন্য এখানে কিছু কোড রয়েছে:

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
এটি সাধারণত 2 ডি তে ব্যবহৃত হয়। ব্যারেন্সেন্ট্রিক সমন্বয়গুলি মানুষকে বিভ্রান্ত করে। এছাড়াও, ত্রিভুজটির সহকারী এবং বিন্দুটি প্রদত্ত, আমি ব্যারিসেনট্রিক্স ব্যবহারের দক্ষতা সম্পর্কে অনিশ্চিত।
কর্নেল কিসিলেউইচিজ

7
@ কর্নেল বারিসেনট্রিক সংস্করণ 2D তেও আরও দক্ষ। আপনার সমাধানটিতেও সমস্যা রয়েছে যে এটি ত্রিভুজটির উপর নির্ভর করে ত্রিভুজটির প্রান্তের ঠিক পয়েন্টের জন্য পৃথক ফলাফলের প্রতিবেদন করবে যা ঘড়ির কাঁটার দিকে বা কাউন্টার ক্লকওয়াইজ ক্রমে নির্দিষ্ট করা হয়েছে।
Andreas Brinck

9
আমার উদ্দেশ্যগুলির জন্য (যে কারণে আমি এই সাইটটি পেয়েছি) কর্নেল কিসিলেউইচজের প্রস্তাবিত মূল উত্তরটি আরও কার্যকর। আমি বিওয়াইটিই আকারের স্থানাঙ্ক এবং একটি খুব সাধারণ মাইক্রোপ্রসেসরের সাথে একটি এলসিডি ডিসপ্লে নিয়ে কাজ করছি যেখানে পূর্ণসংখ্যা বহুগুণ হ'ল একটি দ্রুত নির্দেশ, এবং বিভাগ অনেক বেশি, ধীর। সংখ্যার বিষয়গুলিও অনেক ছোট, কোনও বিভাগের কারণে! সমস্ত গণনা হুবহু ধন্যবাদ, রিক

4
সুতরাং সাইন () ফাংশন আপনাকে জানিয়ে দেয় যে হাফ প্লেনের কোন দিকটি (পি 2 এবং পি 3 এর মধ্যে লাইন দ্বারা গঠিত) পি 1?
ডেভিড ডোরিয়া

1
মনে রাখবেন যে আপনি যদি शिरোখণ্ডের কিছু ক্রম ধরে থাকেন (ঘড়ির কাঁটার বিপরীতে বলুন), আপনাকে সমস্ত সময় নির্ধারকগুলির গণনা করার দরকার নেই। প্রকৃতপক্ষে সর্বোত্তম ক্ষেত্রে, 1 নির্ধারকটি এটির জন্য যথেষ্ট যে পয়েন্টটি ত্রিভুজের ভিতরে নেই।
Thash

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
কর্নেলের পদ্ধতিতে তুচ্ছ প্রস্থানগুলি (প্রয়োগ করা হয়নি) সহ, তিনি আসলে আপনার চেয়ে অনেক বেশি দক্ষ can যদি আপনি আসলে s এবং t গণনা করার চেষ্টা করেন তবে আপনি আমার অর্থ কী তা জানবেন।

85
আমি এটি পরীক্ষা করতে চেয়েছিলাম তাই আমি @sreasdr সমাধান এবং কোপোক মন্তব্যের উপর নির্ভর করে একটি জেএসফিডাল করেছি: jsfiddle.net/PerroAZUL/zdaY8/1
urraka

5
অপ্টিমাইজেশান: s + t <= 1বোঝা s <= 1এবং t <= 1যদি s >= 0এবং t >= 0
টমাস এডিং

7
নিবন্ধ totologic.blogspot.fr/2014/01/... @Logic ডাকযোগে প্রস্তাবিত আমাকে ভাল এই সমাধান বুঝতে সাহায্য করেছিল
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: একটি আরো উন্নত গণনীয় দক্ষতা জন্য, দেখুন coproc নিচে এর মন্তব্যে (যা বিন্দু যে যদি ত্রিভুজ নোড (ঘড়ির কাঁটার দিকে বা ঘড়ির কাঁটার বিপরীতে) সজ্জার পূর্বেই দ্বারা পরিচিত হয় বিভাজন তোলে 2*Areaএক্সপ্রেশন জন্য sএবং tহতে পারে এড়িয়ে যাওয়া)। আরও দেখুন Perro Azul এর jsfiddle-কোড অধীনে মন্তব্য আন্দ্রিয়াস Brinck এর উত্তর।


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|
কোপোক্র

1
আমি যোগ করতে পারেন যে যদি p0->p1->p2হয় ঘড়ির কাঁটার বিপরীতে মধ্যে কার্টিজিয়ান (যা সাধারণত ঘড়ির কাঁটার মধ্যে পর্দা স্থানাঙ্ক ), Areaএই পদ্ধতি দ্বারা গণনা করা ইতিবাচক হতে হবে।
rhgb

1
@ ব্যবহারকারী 2600366 আপনি যখন p0 -> p1 -> p2 -> p0 এবং ত্রিভুজের সীমানা বরাবর ভ্রমণ করেন তখন আপনার ত্রিভুজের অভ্যন্তরটি সর্বদা আপনার ডানদিকে বা সর্বদা আপনার বামে থাকবে। পূর্ববর্তী ক্ষেত্রে, নম্বরটি ঘড়ির কাঁটার দিকে, পরবর্তী ক্ষেত্রে এটি ঘড়ির কাঁটার বিপরীতে থাকে।
andreasdr

47

গুগলের সাথে চূড়ান্ত চেষ্টা করার আগে এবং এই পৃষ্ঠাটি সন্ধানের আগে আমি এই কোডটি লিখেছিলাম, তাই আমি ভেবেছিলাম এটি ভাগ করে নেব। এটি মূলত কিসিলেউইচজ উত্তরের একটি অনুকূলিত সংস্করণ। আমি বেরিয়েনট্রিক পদ্ধতিটিও দেখেছি তবে উইকিপিডিয়া নিবন্ধ থেকে বিচার করে এটি কীভাবে আরও কার্যকর হয় তা বুঝতে আমার খুব কষ্ট হয় (আমি অনুমান করছি যে এর মধ্যে আরও গভীর সমতা রয়েছে)। যাইহোক, এই অ্যালগরিদমের বিভাগ ব্যবহার না করার সুবিধা রয়েছে; একটি সম্ভাব্য সমস্যা হ'ল ওরিয়েন্টেশনের উপর নির্ভর করে প্রান্ত সনাক্তকরণের আচরণ।

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 এবং AC উভয় লাইনের বামে বা ডানদিকে? যদি সত্য হয় তবে এটি ভিতরে থাকতে পারে না। যদি মিথ্যা হয় তবে এটি কমপক্ষে "শঙ্কু" এর মধ্যে থাকে যা শর্তটি পূরণ করে। এখন যেহেতু আমরা জানি যে ত্রিগুনের (ত্রিভুজ) অভ্যন্তরের বিন্দু অবশ্যই বিসি (এবং সিএ) এর মতো AB এর একই দিকে হওয়া উচিত, আমরা পরীক্ষা করে দেখি যে এগুলি পৃথক কিনা। যদি তারা এটি করে, গুলি সম্ভবত ভিতরে থাকতে পারে না, অন্যথায় এস অবশ্যই ভিতরে থাকা উচিত।

গণনার কয়েকটি কীওয়ার্ড হ'ল লাইন অর্ধ-প্লেন এবং নির্ধারক (2x2 ক্রস পণ্য)। সম্ভবত আরও শিক্ষাগত উপায় সম্ভবত এটি এন্টি পয়েন্ট হিসাবে মনে করা যদি এটি AB, বিসি এবং সিএ প্রতিটি লাইন একই পাশ (বাম বা ডান) হয়। উপরের উপায়টি কিছু অপ্টিমাইজেশনের জন্য আরও ভাল ফিট বলে মনে হয়েছিল।


2
এই পরীক্ষাটি প্রদত্ত প্রথমটির তুলনায় প্রায় 140-180% দ্রুত (আপনারা উভয়কে বিটিডব্লিউ :) ধন্যবাদ। আমি এখানে কোডটি চালিয়েছি : পেস্ট.বুন্টু.com / p / k5w7ywH4p8 অপটিমাইজেশন সহ নোডেজ ভি 8 ইঞ্জিন ব্যবহার করে নিম্নলিখিত ফলাফল পেয়েছি: w! নোড-পি --মিনিমাল টেস্ট 1: 114.852ms টেস্ট 2: 64.330ms টেস্ট 1: 115.650ms পরীক্ষা 2: 63.491ms পরীক্ষা 1: 117.671ms পরীক্ষা 2: 65.353ms পরীক্ষা 1: 119.146ms পরীক্ষা 2: 63.871ms পরীক্ষা 1: 118.271ms পরীক্ষা 1: 118.670ms পরীক্ষা 2: 63.352ms
সার্জজি

@ সরজমকিজি আপনি কেন এটি অপ্টিমাইজেশন ছাড়াই চালাবেন? তখন কি বাস্তবতা থেকে আরও সরানো হয় না?
xuiqzy

@ এক্সুইজি ওয়েল, আমার প্রোগ্রামে দুটি ভিন্ন সমাধান রয়েছে। এটি করার দ্রুততম পদ্ধতিটি আমার কাছে এখনও চালানো হয়নি। সম্ভবত সেই মন্তব্যটি মুছে ফেলা উচিত এবং এ সম্পর্কিত আমার সম্পন্ন কাজগুলির সাথে প্রতিস্থাপন করা উচিত ..
সার্জকজি

33

Andreasdr এবং পেরো আজুল পোস্ট করেছেন বারিসেন্ট্রিক পদ্ধতির সি # সংস্করণ। লক্ষ্য করুন এলাকায় হিসাব যদি এড়ানো যায় 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);
}

@ পিয়ারের প্রস্তাবিত পরিবর্তনটি [ সম্পাদনা ]
স্বীকৃত; মন্তব্য দেখুন


বিবৃতিটি ঘড়ির কাঁটার দিকে এবং ঘড়ির কাঁটার দিকের ত্রিভুজ পয়েন্টগুলির জন্য কাজ করে তবে সমাপ্তির সমাধান।
লুক ডুপিন

@ লুকডুপিন নিশ্চিত নয় যে আমি আপনার মন্তব্যটি বুঝতে পেরেছি। এই উত্তরটি 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 এফ / পয়েন্ট 2 এফ টিপলস ব্যবহার করতে এটি উন্নত করতে পারে।
অ্যালেক্স বাইথ

10

একটি সহজ উপায়:

ত্রিভুজের তিনটি উল্লম্ব প্রত্যেকটির সাথে বিন্দু সংযোগকারী ভেক্টরগুলি সন্ধান করুন এবং সেই ভেক্টরগুলির মধ্যে কোণগুলি যোগ করুন। যদি কোণগুলির যোগফল 2 * পাই হয় তবে বিন্দুটি ত্রিভুজের ভিতরে থাকে।

দুটি ভাল সাইট যা বিকল্প ব্যাখ্যা করে:

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;
}

কোড পেরো আজুল জসফিডে আটকানো যায় বা নীচে "কোড স্নিপেট চালান" ক্লিক করে চেষ্টা করে দেখতে পারেন

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
  • বিভাগ: কিছুই না
  • তুলনা: 4

এটি কর্নেল কিসিলেউইকস দ্রবণ (25 স্মরণ, 1 স্টোরেজ, 15 বিয়োগ, 6 গুণ এবং 5 টি তুলনা) এর সাথে বেশ ভাল তুলনা করে এবং ঘড়ির কাঁটা / পাল্টা-ঘড়ির কাঁটার দিকনির্দেশ সনাক্তকরণ প্রয়োজন হলে এটি আরও ভাল হতে পারে (যা 6 প্রত্যাহার, 1 সংযোজন, 2 বিয়োগফল গ্রহণ করে , আরএইচজিবি দ্বারা নির্দেশিত হিসাবে বিশ্লেষণাত্মক সমাধান নির্ণায়ক ব্যবহার করে 2 টি গুণ এবং নিজেই 1 টি তুলনা )।


সুন্দর সমাধান। আমি মনে করি এমএসইতে
জ্যাক ডি'উরিজিও

আমি কোডটি ঠিক তেমনভাবে পরীক্ষিত করেছি এবং এটি আমার পক্ষে কাজ করে না (উদাহরণ পি -4.69317198, -6.99191951 p0 -7.05846786 0.596718192 পি 1 -6.8703599 -2.36565161 পি 2 -4.69317198, -6.99191951)
জিওভানি ফঞ্চাল

@ জিওভান্নিফঞ্চাল স্ট্রেঞ্জ, আপনার উদাহরণটি আমার পক্ষে কাজ করেছে জিসফিডেলে (প্রাথমিক "পয়েন্ট" এবং "ত্রিভুজ" সংজ্ঞাগুলি প্রতিস্থাপন করুন) এবং আমার স্থানীয় পাইথনের বাস্তবায়ন। সংক্ষিপ্ত নির্ভুলতার সমস্যাগুলি (কিছু দশমিক ছাঁটা চেষ্টা করুন)?
Cédric Dufour

1
আপনার আমার পরীক্ষায় দ্রুততম বলে মনে হচ্ছে: jsfiddle.net/eyal/gxw3632c/27 । যদিও সমস্ত পদ্ধতির মধ্যে পার্থক্যটি বেশ কম।
এয়াল

ত্রিভুজ (-1, -1), (1, -1), (0,1) এবং পয়েন্ট (0, -1) ব্যবহার করে দেখুন। সত্য (when) + টি (২)> ডি (২) হওয়া উচিত হলে মিথ্যা প্রত্যাবর্তন করে। ত্রিভুজের কিনারায় গণিতে কিছু ভুল আছে বলে মনে হচ্ছে, পয়েন্ট p ঠিক p0 এবং p1 এর সীমানায় এবং এটি একটি <কে একটি <= বা এমন কিছু রূপান্তরিত করার সাধারণ বিষয় নয়।
ডিভনুলিকাস

5

আমি যা করি তা হ'ল তিনটি মুখের স্বাভাবিক অবস্থা,

  • পাশের ভেক্টর এবং মুখের সাধারণ ভেক্টরের ক্রস প্রোডাক্ট দ্বারা 3D তে।

  • 2D তে কেবল উপাদানগুলি অদলবদল করে এবং একটিকে অবহেলা করে,

এরপরে / বাইরে কোনও একদিকে যেমন তখন পাশের একটি বিন্দু পণ্য স্বাভাবিক এবং বিন্দুতে ভেক্টরটি চিহ্নিত করতে, চিহ্নটি পরিবর্তন করে। অন্য দুটি (বা আরও) পক্ষের জন্য পুনরাবৃত্তি করুন।

উপকারিতা:

  • একই ত্রিভুজটিতে একাধিক পয়েন্ট পরীক্ষার জন্য অনেকগুলি প্রাক্কলকুলেটেড।

  • অভ্যন্তরীণ পয়েন্টগুলির চেয়ে বাইরের সাধারণ ক্ষেত্রে প্রথম দিকে প্রত্যাখ্যান। (এছাড়াও যদি বিন্দু বিতরণটি একদিকে ওজনিত হয় তবে প্রথমে সেই দিকটি পরীক্ষা করতে পারে))


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 তিনটি সাজানো মান হতে দিন be তাদের মাধ্যমে তিনটি অনুভূমিক অঙ্কন করে আপনি বিমানটিকে দুটি অর্ধেক প্লেন এবং দুটি স্ল্যাবে বিভক্ত করুন। 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

আরও দুটি তুলনা ব্যয় করে। আপনি যেমন দেখেন যে, "বাউন্ডিং স্ল্যাব" এর বাইরে পয়েন্টগুলির জন্য দ্রুত প্রত্যাখ্যান করা সম্ভব।

Allyচ্ছিকভাবে, আপনি বাম এবং ডানদিকে দ্রুত প্রত্যাখ্যানের জন্য অ্যাবসিসাসাসে একটি পরীক্ষা সরবরাহ করতে পারেন (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সর্বোচ্চ প্রান্ত জন্য। এই রূপান্তরটি ত্রিভুজটির এই দিকটিকে উল্লম্ব করে দেবে। আপনি যেহেতু মাঝের অনুভূমিকের কোন দিকে আছেন তা আপনি জানেন, সুতরাং ত্রিভুজটির একক দিকের সাথে সাইনটি পরীক্ষা করা যথেষ্ট।

এখানে চিত্র বর্ণনা লিখুন

ধরে নিলে আপনি precালুটিকে পূর্বরূপ 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 

}

সম্পাদনা: ডিটি গণনার জন্য একটি টাইপ ছিল ( 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>

এখানে চিত্র বর্ণনা লিখুন

আমি এখানে উপরে বর্ণিত একই পদ্ধতি ব্যবহার করছি: প্রতিটি পংক্তির বিবি, বিসি, সিএর যথাক্রমে "একই" পাশে যদি এটি যথাক্রমে হয় তবে এ বি সি-র ভিতরে একটি পয়েন্ট রয়েছে is

ত্রিভুজ অন্তর্ভুক্তির উদাহরণ


আমি এই কোডটি ক্লান্ত করেছি এবং এটি কার্যকর হয় না। এটি সর্বদা মিথ্যা প্রদান করে।
x অ্যাপল

হুমমম ... আপনি সম্ভবত ভুল করেছেন এখানে সেই ফাংশনটি চলতে চলেছে
জোসেফ Merdrignac

আমি আপনার পাইথনের প্রতিক্রিয়া দেখেছি, আমরা একই পদ্ধতিটি ব্যবহার করছি, যদি আমি আরও একটি লাইন ব্যবহার করি ( let det = (bx - ax) * (cy - ay) - (by - ay) * (cy - ay)), এটি ত্রিভুজটি ঘুরানোর ক্রম নির্ধারণ করার জন্য, সুতরাং পদ্ধতিটি সিডাব্লু এবং সিসিডাব্লু ত্রিভুজগুলির সাথে কাজ করবে (জেএসফিডাল দেখুন)।
জোসেফ মেরড্রিগনাক

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 এর অভ্যন্তরে থাকতে হবে A.

এখানে চিত্র বর্ণনা লিখুন

  1. যদি আরও সীমাবদ্ধ করে, এবং টি [0, 1] এর সাথে সম্পর্কিত। আমরা এরিয়া বি পেয়েছি যা এস * ভি02 + টি * ভি01 এর সমস্ত ভেক্টর সমন্বিত রয়েছে, এর শর্ত, টি [0, 1] এর সাথে সম্পর্কিত। এটি লক্ষণীয় যে অঞ্চল বি এর নীচের অংশটি ত্রিভুজ v0, v1, v2 এর আয়না। সমস্যাটি আসে যদি আমরা অঞ্চল বি এর নিম্ন অংশ বাদে আরও কিছু শর্ত, এবং টি দিতে পারি তবে to

এখানে চিত্র বর্ণনা লিখুন

  1. ধরা যাক আমরা একটি মান দিয়েছি এবং টি [0, 1] এ পরিবর্তিত হচ্ছে। নিম্নলিখিত ছবিতে, পয়েন্ট পিটি v1v2 এর প্রান্তে রয়েছে। S * v02 + t * v01 এর সমস্ত ভেক্টর যা সাধারণ ভেক্টরের সমষ্টি দ্বারা ড্যাশ লাইনের সাথে থাকে। ভি 1 ভি 2 এবং ড্যাশ লাইন ক্রস পয়েন্ট পি তে, আমাদের রয়েছে:

(1-গুলি) | v0v2 | / | v0v2 | = টিপি | v0v1 | / | v0v1 |

আমরা 1 - s = tp পাই, তারপরে 1 = s + টিপি হবে। যদি কোনও টি> টিপি, কোন ডাবল ড্যাশ লাইনে 1 <s + t থাকে তবে ভেক্টরটি ত্রিভুজের বাইরে থাকে, যে কোনও t <= tp, যা 1> = s + t যেখানে একক ড্যাশ লাইনে থাকে, ভেক্টর হয় ত্রিভুজ ভিতরে।

তারপরে যদি আমরা [0, 1] এ কোনও এস প্রদান করি তবে ত্রিভুজের অভ্যন্তরে ভেক্টরের জন্য সংশ্লিষ্ট টি টি অবশ্যই 1> = s + t পূরণ করতে হবে।

এখানে চিত্র বর্ণনা লিখুন

সুতরাং পরিশেষে আমরা v = s * v02 + t * v01 পেয়েছি, v এর সাথে ত্রিভুজের ভিতরে রয়েছে এস, টি, এস + টি [0, 1] এর সাথে সম্পর্কিত। তারপরে অনুবাদ করুন, আমাদের আছে

p - p0 = s * (p1 - p0) + টি * (p2 - p0), এস, টি, এস + টি সহ [0, 1]

যা সমীকরণ সিস্টেমকে p = p0 + s * (p1 - p0) + টি * (পি 2 - পি 0) সমাধান করার জন্য অ্যান্ড্রেসের সমাধান হিসাবে একই, এস, টি, এস + টি [0, 1] এর সাথে সম্পর্কিত।


আপনি কেবল এটি বলতে পারেন যে আপনি তিনটি উল্লম্ব দ্বারা সংজ্ঞায়িত স্থানীয় ফ্রেমটি ব্যবহার করেন যাতে পক্ষগুলি s = 0, t = 0 এবং s + t = 1 হয়ে যায়। অ্যাফাইন স্থানাঙ্ক রূপান্তর হ'ল লিনিয়ার বীজগণিতের একটি সুপরিচিত অপারেশন।
ইয়ভেস দাউস্ট

2

অজগরটিতে এখানে একটি সমাধান রয়েছে যা দক্ষ, ডকুমেন্টেড এবং তিনটি ইউনিট রয়েছে। এটি পেশাদার-গ্রেড মানের এবং যেমনটি মডিউল আকারে আপনার প্রকল্পে ফেলে দেওয়া প্রস্তুত।

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)

উপরে এটির বৈধতা নিশ্চিত করার জন্য একটি অতিরিক্ত alচ্ছিক গ্রাফিকাল পরীক্ষা রয়েছে:

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

সমস্যাযুক্ত প্রান্তের শর্ত রয়েছে যেখানে দুটি সংলগ্ন ত্রিভুজগুলির সাধারণ প্রান্তে একটি বিন্দু হুবহু। বিন্দু উভয় বা ত্রিভুজ দুটি হতে পারে না। পয়েন্টটি নির্ধারণের জন্য আপনার একটি স্বেচ্ছাসেবী কিন্তু ধারাবাহিক উপায় দরকার। উদাহরণস্বরূপ, বিন্দু দিয়ে একটি অনুভূমিক রেখা আঁকুন। লাইনটি ডানদিকে ত্রিভুজটির অন্য পাশের সাথে ছেদ করলে বিন্দুটিকে ত্রিভুজের অভ্যন্তরের মতো মনে করা হবে treated ছেদটি যদি বাম দিকে থাকে তবে বিন্দুটি বাইরে।

বিন্দুটি যে রেখায় অবস্থিত তা যদি অনুভূমিক হয় তবে উপরে / নীচে ব্যবহার করুন।

যদি বিন্দু একাধিক ত্রিভুজগুলির সাধারণ প্রান্তে থাকে তবে ত্রিভুজটি ব্যবহার করুন যার কেন্দ্রের সাথে বিন্দুটি সবচেয়ে ছোট কোণ গঠন করে।

আরও মজাদার: তিনটি পয়েন্ট একটি সরলরেখায় (শূন্য ডিগ্রি) হতে পারে, উদাহরণস্বরূপ (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

সবচেয়ে সহজ উপায় এবং এটি সমস্ত ধরণের ত্রিভুজগুলির সাথে কাজ করে তা কেবল পি পয়েন্ট এ, বি, সি পয়েন্ট কোণগুলির কোণ নির্ধারণ করে। যদি কোনও কোণ 180.0 ডিগ্রির চেয়ে বড় হয় তবে এটি বাইরে, যদি 180.0 হয় তবে এটি পরিধির উপরে রয়েছে এবং যদি অ্যাকোস আপনাকে প্রতারণা করে এবং 180.0 এরও কম হয় তবে এটি ভিতরে is http: // গণিত-পদার্থবিজ্ঞান বোঝার জন্য একবার নজর দিন -psychology.blogspot.hu/2015/01/earlish-determination-that-point-is.html


0

সত্যিই এটি সাইমন পি স্টিভেনের উত্তরের মতোই সহজ তবে এই পদ্ধতির সাথে আপনার ত্রিভুজের কিনারাগুলির পয়েন্টগুলি অন্তর্ভুক্ত করা উচিত কিনা সে বিষয়ে আপনার কোনও দৃ control় নিয়ন্ত্রণ নেই।

আমার পন্থাটি একটু আলাদা তবে খুব বেসিক। নিম্নলিখিত ত্রিভুজটি বিবেচনা করুন;

এখানে চিত্র বর্ণনা লিখুন

ত্রিভুজের বিন্দু থাকতে আমাদের 3 টি শর্ত পূরণ করতে হবে

  1. ACE কোণ (সবুজ) ACB কোণ (লাল) এর চেয়ে ছোট হওয়া উচিত
  2. ইসিবি কোণ (নীল) ACB কোণ (লাল) এর চেয়ে ছোট হওয়া উচিত
  3. পয়েন্ট ই এবং পয়েন্ট সি জোরে যখন একই চিহ্ন এবং y মানগুলি AB | সমীকরণের সাথে প্রয়োগ করা হয় তখন একই চিহ্ন থাকে লাইন।

এই পদ্ধতিতে আপনার পৃথকভাবে প্রান্তের বিন্দুটি অন্তর্ভুক্ত বা বাদ দেওয়ার সম্পূর্ণ নিয়ন্ত্রণ রয়েছে। সুতরাং আপনি পরীক্ষা করতে পারেন যে কোনও পয়েন্ট কেবলমাত্র | এসি | সহ ত্রিভুজটিতে আছে কিনা উদাহরণস্বরূপ প্রান্ত।

সুতরাং জাভাস্ক্রিপ্টে আমার সমাধানটি নীচে হবে;

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);
}

এর চেয়ে দক্ষ আর হতে পারে না! ত্রিভুজের প্রতিটি পাশের স্বতন্ত্র অবস্থান ও অভিমুখীকরণ থাকতে পারে, সুতরাং তিনটি গণনা: l1, l2 এবং l3 অবশ্যই প্রতিটি 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;
} 

বেরিসেন্ট্রিক থেকে রূপান্তরিত প্রায় নিখুঁত কার্টেসিয়ান স্থানাঙ্কগুলি * ভি (এক্স) এবং * ডাব্লু (ওয়াই) ডাবলসের মধ্যে রফতানি করা হয়। উভয় রফতানি দ্বৈত প্রতিটি ক্ষেত্রে আগে একটি * চর থাকা উচিত, সম্ভবত: * ভি এবং * ডাব্লু কোডও একটি চতুর্ভুজটির অন্য ত্রিভুজের জন্য ব্যবহার করা যেতে পারে। এই দ্বারা স্বাক্ষরিত ক্লকওয়াইস এভিসিডি কোয়াড থেকে কেবল ত্রিভুজ এ বি সি লিখেছেন।

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

দ্বি ত্রিভুজের সাথে পরীক্ষার জন্য এই পয়েন্টটি এবিসি ত্রিভুজের অভ্যন্তরে রয়েছে এই ফাংশনটিকে সিডিএ দিক নির্দেশ করুন এবং চতুর্ভুজটির পরে *v=1-*v;এবং ফলাফলগুলি সঠিক হওয়া উচিত*w=1-*w;


-1

যখন "ত্রিভুজগুলি ঘড়ির কাঁটার দিক দিয়ে থাকবে" আপনি যখন নিশ্চিত হন তখন আমার "কনট্রোলএবল এনভায়রনমেন্ট" এ ত্রিভুজ চেক ইন পয়েন্ট দরকার ছিল। সুতরাং, আমি পেরো আজুলের জেসফিডাল নিয়েছি এবং এ জাতীয় মামলার জন্য কোপ্রোকের পরামর্শ অনুসারে এটি সংশোধন করেছি ; অপ্রয়োজনীয় 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>

এখানে ইউনিটির সমতুল্য সি # কোড রয়েছে:

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

ত্রিভুজের শীর্ষাংশ (x1, y1), (x2, y2), (x3, y3) দ্বারা গঠিত অঞ্চলটি ইতিবাচক কিনা তা যাচাই করার সহজতম উপায়গুলির মধ্যে একটি।

সূত্র দ্বারা ক্ষেত্রফল গণনা করা যেতে পারে:

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])]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.