লাইনের সংঘর্ষে 2D লাইন কীভাবে সনাক্ত করা যায়?


13

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

রেফারেন্সের জন্য এটি আমি তৈরির সাথে একটি অনুরূপ গেম: শিরোনামহীন ফ্ল্যাশ গেম

আমি এই শৃঙ্খলাবদ্ধ খেলাটি প্রায় যুক্তি পূর্ণতার জন্য তৈরি করেছি। কিন্তু, যখন দুটি লাইন ছেদ করে, আমার আলাদা রঙ দেখানোর জন্য সেই ছেদযুক্ত বা 'জটযুক্ত' রেখাগুলি প্রয়োজন; লাল।

আপনি যদি লাইনের অংশের সংঘর্ষগুলি সনাক্ত করার জন্য একটি অ্যালগরিদম প্রস্তাব করতে পারেন তবে আপনার লোকদের জন্য সত্যই তা হবে । আমি মূলত এমন একজন ব্যক্তি যিনি 'গাণিতিকভাবে' চেয়ে 'দৃষ্টিবদ্ধ' ভাবতে পছন্দ করেন :)

সম্পাদনা: ধারণাটি আরও স্পষ্ট করে জানাতে আমি কয়েকটি ডায়াগ্রাম যুক্ত করতে চাই

কোন ছেদ নেই কোন ছেদ নেই ছেদ কোন ছেদ নেই

পিএস আমি একটি ফাংশন করার চেষ্টা করছি

private function isIntersecting(A:Point, B:Point, C:Point, D:Point):Boolean

আগাম ধন্যবাদ.


6
এটি সমস্যার হতাশাজনকভাবে অ-ভিজ্যুয়াল ব্যাখ্যা, তবে এটি একটি অ্যালগরিদম এবং আপনি যদি তাদের গণিত পড়তে নিজেকে নিয়ে আসতে পারেন তবে তা বোঝা যায়: লোকাল.ওয়াস্প.ইউওয়া.এডু.উ / অ্যাপপোর্ক / জ্যামিতি / লাইনলাইন 2 ডি এটি হতে পারে ভারী হোন যদি আপনার ভেক্টরের গণিত দুর্বল হয়। আমি বুঝতে পারি - আমি চাক্ষুষ ব্যাখ্যাও পছন্দ করি। আমি এটি ডুডল করার জন্য পরে সময় বের করার চেষ্টা করব, তবে যদি শিল্পিতভাবে ঝুঁকে পড়া কেউ যদি এই লিঙ্কটি দেখেন এবং আমার আগে সময় পান তবে তা পেতে!
আনকো

উত্তর:


18

আমি নিম্নলিখিত পদ্ধতিটি ব্যবহার করি যা প্রায় এই অ্যালগরিদমের বাস্তবায়ন । এটি সি # তে রয়েছে তবে এ্যাকশনস্ক্রিপ্টে অনুবাদ করা তুচ্ছ হওয়া উচিত।

bool IsIntersecting(Point a, Point b, Point c, Point d)
{
    float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));
    float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));
    float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));

    // Detect coincident lines (has a problem, read below)
    if (denominator == 0) return numerator1 == 0 && numerator2 == 0;

    float r = numerator1 / denominator;
    float s = numerator2 / denominator;

    return (r >= 0 && r <= 1) && (s >= 0 && s <= 1);
}

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

সম্পাদন করা

এই অ্যালগরিদম থেকে আমি কোনও ফল পাইনি, দুঃখিত!

এটি আশ্চর্যজনক, আমি এটি পরীক্ষা করেছি এবং এটি উপরে বর্ণিত একক ক্ষেত্রে ব্যতীত আমার পক্ষে কাজ করছে। উপরে পোস্ট করা ঠিক একই সংস্করণটি ব্যবহার করে আমি পরীক্ষার ড্রাইভ নেওয়ার সময় এই ফলাফলগুলি পেয়েছি:

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


এই অ্যালগরিদম থেকে আমি কোনও ফল পাইনি, দুঃখিত!
বিষ্ণু

4
@ વિશ আপনার কী সমস্যা ছিল? আমি পোস্ট করার আগে অ্যালগরিদমের এই সঠিক অনুলিপিটি পরীক্ষা করেছি এবং বর্ণিত একক কেস ব্যতীত এটি নির্দোষভাবে কাজ করেছে।
ডেভিড গওভিয়া

তারপরে, আমাকে আবার চেষ্টা করতে দিন, আমি এটিতে কিছু গাণিতিক মিশ্রিত করতে পারি। আমি শীঘ্রই আপনাকে জানাতে হবে। ধন্যবাদ একটি টন, এনওয়েজ :)
বিষ্ণু

1
আমি আপনার দ্বারা অ্যালগরিদম থেকে পছন্দসই ফলাফল পেয়েছি, ধন্যবাদ @ ডেভিডগুভিয়া।
বিষ্ণু

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

4

বিভাগ ছাড়া! সুতরাং নির্ভুলতা বা শূন্য দ্বারা বিভাগ দ্বারা কোন সমস্যা।

লাইন বিভাগ 1 এ A থেকে বি লাইন বিভাগ 2 সি থেকে ডি

একটি লাইন কখনই শেষ না হওয়া রেখা, লাইন বিভাগটি সেই লাইনের একটি সংজ্ঞায়িত অংশ।

দুটি আবদ্ধ বাক্স ছেদ করে কিনা তা পরীক্ষা করুন: যদি কোনও ছেদ নেই -> ক্রস নেই! (গণনা শেষ হয়েছে, মিথ্যা ফিরুন)

লাইন সেজ 1 টি স্ট্র্যাডলস লাইন সেগ 2 এবং যদি লাইন সেজ 2 টি স্ট্র্যাডলস লাইন সেগ 1 (যেমন লাইন সেগমেন্ট 1 লাইন বিভাগ 2 দ্বারা সংজ্ঞায়িত লাইনের উভয় প্রান্তে রয়েছে কিনা) তা পরীক্ষা করুন।

এটি সমস্ত পয়েন্ট -A দ্বারা অনুবাদ করে তৈরি করা যেতে পারে (যেমন আপনি 2 টি লাইন সরান সুতরাং A এর মূল হয় (0,0))

তারপরে আপনি পরীক্ষা করতে হবে যে বিন্দু C এবং D লাইনটির বিভিন্ন দিকে 0,0 থেকে বি দ্বারা সংজ্ঞায়িত হয়েছে কিনা

//Cross Product (hope I got it right here)
float fC= (B.x*C.y) - (B.y*C.x); //<0 == to the left, >0 == to the right
float fD= (B.x*D.y) - (B.y*D.x);

if( (fc<0) && (fd<0)) //both to the left  -> No Cross!
if( (fc>0) && (fd>0)) //both to the right -> No Cross!

যদি আপনি ইতিমধ্যে "নো ক্রস" না পেয়ে থাকেন তবে এ, বি বনাম সি, ডি কিন্তু সি, ডি বনাম এ, বি ব্যবহার না করে চালিয়ে যান (একই ক্যালকগুলি, কেবলমাত্র এ এবং সি, বি এবং ডি) অদলবদল করে না থাকলে, "ক্রস নেই!" তাহলে আপনার একটি ছেদ আছে!

আমি ক্রস পণ্যটির জন্য সঠিক গণনা অনুসন্ধান করেছি এবং এই ব্লগ পোস্টটি খুঁজে পেয়েছি যা পদ্ধতিটিও ব্যাখ্যা করে।


1
আমি দুঃখিত, তবে আমি ভেক্টর ম্যাথগুলিতে বেশ ভাল নই, আমি এই অ্যালগরিদমটিকে এরূপ হিসাবে প্রয়োগ করেছি, তবে কোনও ফল পাইনি, দুঃখিত!
বিষ্ণু

1
এটি কাজ করা উচিত তাই আপনি যদি আমাদের আপনার কোডটি প্রদর্শন করতে পারেন তবে আমরা আপনাকে সেখানে সহায়তা করতে পারি?
ভালমন্ড

নিস! তবে লিঙ্কটি নষ্ট
ক্লাব 45

ছেদ বিন্দুটি পেতে আপনি এতে কিছু যুক্ত করতে পারেন কি?
সানরেমে

1

আমি কেবল বলতে চাই, আমার গেমমেকার স্টুডিও গেমের জন্য এটির দরকার ছিল এবং এটি ভালভাবে কাজ করে:

///scr_line_collision(x1,y1,x2,y2,x3,y3,x4,y4)

var denominator= ((argument2 - argument0) * (argument7 - argument5)) - ((argument3 - argument1) * (argument6 - argument4));
var numerator1 = ((argument1 - argument5) * (argument6 - argument4)) - ((argument0 - argument4) * (argument7 - argument5));
var numerator2 = ((argument1 - argument5) * (argument2 - argument0)) - ((argument0 - argument4) * (argument3 - argument1));

// Detect coincident lines
if (denominator == 0) {return (numerator1 == 0 && numerator2 == 0)}

var r = numerator1 / denominator;
var s = numerator2 / denominator;

return ((r >= 0 && r <= 1) && (s >= 0 && s <= 1));

আমি মনে করি যে কোডটি কী করে তা যদি আপনি ব্যাখ্যা করেন তবে এই উত্তরটি সত্যিই উন্নতি করতে পারে।
টমটস্যাগ্ক

1

গ্রহণযোগ্য উত্তর এক্ষেত্রে একটি ভুল উত্তর দিয়েছে:

x1 = 0;
y1 = 0;
x2 = 10;
y2 = 10;

x3 = 10.1;
y3 = 10.1;
x4 = 15;
y4 = 15;

এই লাইনগুলি স্পষ্টতই ছেদ করে না, তবে "সঠিক উত্তর" এর ক্রিয়া অনুসারে লাইনগুলি ছেদ করে না।

এটি আমি ব্যবহার করি:

function do_lines_intersect(px1,py1,px2,py2,px3,py3,px4,py4) {
  var ua = 0.0;
  var ub = 0.0;
  var ud = (py4 - py3) * (px2 - px1) - (px4 - px3) * (py2 - py1);


  if (ud != 0) {
    ua = ((px4 - px3) * (py1 - py3) - (py4 - py3) * (px1 - px3)) / ud;
    ub = ((px2 - px1) * (py1 - py3) - (py2 - py1) * (px1 - px3)) / ud;
        if (ua < 0.0 || ua > 1.0 || ub < 0.0 || ub > 1.0) ua = 0.0;
  }

  return ua;
}

0 = রেখাগুলি ছেদ করে না returns

রিটার্ন> 0 = রেখাগুলি ছেদ করে


প্রশ্নের উত্তর দিতে আপডেট করুন:

আমি এই কোডটি নিজে তৈরি করি নি। এটি 5 বছরেরও বেশি পুরানো এবং মূল উত্স কী তা আমি জানি না। কিন্তু ..

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

l = do_lines_intersect(...)
if (l > 0) {
    intersect_pos_x = l * (px2-px1);
    intersect_pos_y = l * (py2-py1);
} else {
    // lines do not cross
}

(আমি এটি পরীক্ষা করি নি)


এর এমন কোনও সংস্করণ আছে যা ছেদ বিন্দুতে ফিরে আসে?
সানরেমে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.