কম্পিউটার টিউটোরিয়াল

বিন্দু পলিগনের ভিতরে আছে কিনা (Check if a given point lies inside a Polygon)


এই সমস্যায়, একটি পলিগন দেওয়া আছে, এবং একটি বিন্দু Pও দেওয়া আছে। আমাদের চেক করতে হবে বিন্দুটি পলিগনের ভিতরে আছে কিনা বাইরে।

এটি সমাধানের জন্য, আমরা বিন্দু P থেকে একটি সরল রেখা টানব। সেটি অনন্ত পর্যন্ত প্রসারিত হবে। রেখাটি অনুভূমিক, অথবা x-অক্ষের সাথে সমান্তরাল।

उस রেখা থেকে, আমরা গণনা করব রেখাটি কতবার পলিগনের বাহুগুলোর সাথে ইন্টারসেক্ট করছে। যখন বিন্দুটি পলিগনের ভিতরে থাকবে, এটি বাহুগুলোর সাথে বিষম সংখ্যক বার ইন্টারসেক্ট করবে, যদি P পলিগনের যেকোনো বাহুয়ে থাকে, তবে এটি জোড় সংখ্যক বার কাটবে। যদি কোনো শর্ত সত্য না হয়, তবে সেটি পলিগনের বাইরে।

ইনপুট এবং আউটপুট

ইনপুট: একটি পলিগনের বিন্দু {(0, 0), (10, 0), (10, 10), (0, 10)}। এবং বিন্দু P (5, 3) চেক করার জন্য। আউটপুট: বিন্দুটি ভিতরে আছে।

অ্যালগরিদম

checkInside(Poly, n, p)

ইনপুট: পলিগনের বিন্দুগুলো, পলিগনের বিন্দুগুলোর সংখ্যা, চেক করার জন্য বিন্দু p।

আউটপুট: সত্য যখন p পলিগনের ভিতরে থাকে, অন্যথায় মিথ্যা।

শুরু 
  যদি n<3, তবে 
    মিথ্যা ফেরত দিন 
  exLine নামক একটি লাইন তৈরি করুন বিন্দু p থেকে অনন্ত পর্যন্ত, রেখার ঢাল 0°। 
  count :=0 এবং i := 0 
  পুনরাবৃত্তি করুন 
    side নামক লাইন তৈরি করুন, বিন্দু poly[i] থেকে poly[(i+1) mod n] পর্যন্ত 
    যদি side এবং exLine ইন্টারসেক্ট করে, তবে 
      যদি side এবং exLine কোলিনিয়ার হয়, তবে 
        যদি বিন্দু p side-এ থাকে, তবে 
          সত্য ফেরত দিন 
        অন্যথায় মিথ্যা ফেরত দিন 
      count := count + 1 
    i := (i + 1) mod n 
  যতক্ষণ i ≠ 0 
  সত্য ফেরত দিন যদি count বিষম হয় 
শেষ

উদাহরণ

#include<iostream> using namespace std; struct Point {   int x, y; }; struct line {   Point p1, p2; }; bool onLine(line l1, Point p) {     //চেক করুন p লাইন-এ আছে কিনা     if(p.x <= max(l1.p1.x, l1.p2.x) && p.x <= min(l1.p1.x, l1.p2.x) &&       (p.y <= max(l1.p1.y, l1.p2.y) && p.y <= min(l1.p1.y, l1.p2.y)))         return true;     return false; } int direction(Point a, Point b, Point c) {   int val = (b.y-a.y)*(c.x-b.x)-(b.x-a.x)*(c.y-b.y);   if (val == 0)     return 0;     //কোলিনিয়ার   else if(val < 0)     return 2;     //অ্যান্টি-ক্লকওয়াইজ দিক     return 1;     //ক্লকওয়াইজ দিক } bool isIntersect(line l1, line l2) {   //দুটি লাইন এবং অন্য লাইনের বিন্দুಗಳಿಗೆ চারটি দিক   int dir1 = direction(l1.p1, l1.p2, l2.p1);   int dir2 = direction(l1.p1, l1.p2, l2.p2);   int dir3 = direction(l2.p1, l2.p2, l1.p1);   int dir4 = direction(l2.p1, l2.p2, l1.p2);   if(dir1 != dir2 && dir3 != dir4)     return true;     //তারা ইন্টারসেক্ট করছে   if(dir1==0 && onLine(l1, l2.p1))     //যখন লাইন2-এর p2 লাইন1-এ থাকে     return true;   if(dir2==0 && onLine(l1, l2.p2))     //যখন লাইন2-এর p1 লাইন1-এ থাকে     return true;   if(dir3==0 && onLine(l2, l1.p1))     //যখন লাইন1-এর p2 লাইন2-এ থাকে     return true;   if(dir4==0 && onLine(l2, l1.p2)) //যখন লাইন1-এর p1 লাইন2-এ থাকে     return true;   return false; } bool checkInside(Point poly[], int n, Point p) {   if(n < 3)     return false;         //যখন পলিগনের ৩টির কম এজ থাকে, সেটি পলিগন নয়   line exline = {p, {9999, p.y}};  //অনন্তে একটি বিন্দু তৈরি করুন, y পয়েন্ট p-এর মতো   int count = 0;   int i = 0;   do {     line side = {poly[i], poly[(i+1)%n]};    //পলিগনের দুটি последовательный বিন্দু থেকে লাইন তৈরি     if(isIntersect(side, exline)) {       //যদি side exline-এ ইন্টারসেক্ট করে       if(direction(side.p1, p, side.p2) == 0)         return onLine(side, p);       count++;     }     i = (i+1)%n;   } while(i != 0);     return count&1;       //যখন count বিষম } int main() {   // line polygon = {{{0,0},{10,0}},{{10,0},{10,10}},{{10,10},{0,10}},{{0,10},{0,0}}};   Point polygon[] = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};   Point p = {5, 3};   int n = 4;   if(checkInside(polygon, n, p))     cout << "Point is inside.";   else     cout << "Point is outside."; }

আউটপুট

Point is inside.

  1. দেওয়া গ্রাফটি ট্রি কিনা তা যাচাই করা

  2. C++-এ একটি বৃত্ত দুই সংকেন্দ্রিক বৃত্তের মধ্যে থাকা রিং-এ সম্পূর্ণরূপে অবস্থিত কিনা তা যাচাই করা

  3. পাইথনে যাচাই করুন পয়েন্ট আয়তাকার (rectangle) এর ভিতরে বা বাউন্ডারি на আছে কিনা

  4. পাইথনে একটি পয়েন্ট পলিগনের ভিতরে বা বাউন্ডারিতে আছে কিনা চেক করার প্রোগ্রাম