বাস্তবসম্মত টার্ন যুক্ত করা হচ্ছে
পরবর্তী পদক্ষেপটি হ'ল আমাদের ইউনিটগুলির জন্য বাস্তব বাঁকানো বাঁকগুলি যুক্ত করা, যাতে তারা প্রতিবার যখন মোড় নেওয়ার দরকার হয় ততক্ষণে হঠাৎ করে দিক পরিবর্তন করতে দেখা যায় না। একটি সহজ সমাধান হ'ল আকস্মিক কোণগুলিকে ঘুরিয়ে দেওয়ার জন্য একটি স্প্লাইন ব্যবহার করে। যদিও এটি কিছু নান্দনিক উদ্বেগের সমাধান করে, এটি এখনও বেশিরভাগ ইউনিটের জন্য শারীরিকভাবে খুব অবাস্তব আন্দোলনের ফলস্বরূপ। উদাহরণস্বরূপ, এটি একটি ট্যাঙ্কের আকস্মিক কোণে একটি শক্ত বাঁকায় পরিবর্তিত হতে পারে, তবে বাঁকানো বাঁকটি ট্যাঙ্কটি কার্য সম্পাদন করতে পারে তার চেয়ে এখনও আরও শক্ত would
আরও ভাল সমাধানের জন্য, আমাদের প্রথমটি জানতে হবে আমাদের ইউনিটের টার্নিং ব্যাসার্ধ। ব্যাসার্ধ ঘুরিয়ে দেওয়া মোটামুটি সহজ ধারণা: আপনি যদি নিজের গাড়িতে একটি বড় পার্কিং লটে থাকেন এবং চাকাটিকে যতদূর যেতে হবে বাম দিকে ঘুরিয়ে ঘুরিয়ে চালাবেন, বৃত্তের ব্যাসার্ধটি আপনার বাঁক ব্যাসার্ধ। একটি ভলসওগেন বিটলের বাঁক ব্যাসার্ধটি একটি বড় এসইউভির তুলনায় যথেষ্ট ছোট হবে এবং কোনও ব্যক্তির বাঁক ব্যাসার্ধ বড়, কাঠের ভালুকের চেয়ে যথেষ্ট কম হবে।
ধরা যাক যে আপনি কোনও মুহুর্তে (উত্স) এবং নির্দিষ্ট দিক নির্দেশ করেছেন এবং চিত্র 5-তে বর্ণিত হিসাবে আপনাকে অন্য কোনও বিন্দুতে (গন্তব্য) পৌঁছাতে হবে, সবচেয়ে ছোট পথটি আপনি যতদূর বাম দিকে ঘুরিয়েই পাওয়া যায় আপনি সরাসরি গন্তব্যের দিকে নির্দেশ না করা পর্যন্ত একটি চেনাশোনাতে যেতে পারেন এবং তারপরে এগিয়ে যেতে পারেন বা ডানদিকে ঘুরিয়ে একই জিনিসটি চালিয়ে যেতে পারেন।
চিত্র 5-এ সংক্ষিপ্ততম রুটটি নীচে পরিষ্কারভাবে সবুজ রেখা। এই পাথটি কিছু জ্যামিতিক সম্পর্কের কারণে গণনা করা মোটামুটি সোজা বলে প্রমাণিত হয়েছে, যা চিত্র 6 এ চিত্রিত হয়েছে।
প্রথমে আমরা পয়েন্ট পি এর অবস্থান গণনা করি, যা আমাদের বাঁকানো বৃত্তের কেন্দ্র, এবং সর্বদা প্রারম্ভিক বিন্দু থেকে দূরে ব্যাসার্ধ হয়। যদি আমরা আমাদের প্রাথমিক দিক থেকে ডান দিকে ঘুরতে থাকি তবে এর অর্থ পি এর উত্স থেকে (প্রাথমিক_নির্দেশ - 90) এর কোণে রয়েছে, সুতরাং:
angleToP = initial_direction - 90
P.x = Origin.x + r * cos(angleToP)
P.y = Origin.y + r * sin(angleToP)
এখন যেহেতু আমরা কেন্দ্রের পয়েন্ট P এর অবস্থান জানি, আমরা চিত্র থেকে h হিসাবে দেখানো পি থেকে গন্তব্যের দূরত্ব গণনা করতে পারি:
dx = Destination.x - P.x
dy = Destination.y - P.y
h = sqrt(dx*dx + dy*dy)
এই মুহুর্তে আমরা এটিও পরীক্ষা করে দেখতে চাই যে গন্তব্যটি বৃত্তের মধ্যে নেই, কারণ এটি যদি হয় তবে আমরা কখনই এটিতে পৌঁছতে পারিনি:
if (h < r)
return false
এখন আমরা বিভাগের d এর দৈর্ঘ্য গণনা করতে পারি, যেহেতু আমরা ইতিমধ্যে h এবং r নামের ডান ত্রিভুজটির অন্য দুটি পক্ষের দৈর্ঘ্য জানি। আমরা ডান ত্রিভুজ সম্পর্ক থেকে কোণ নির্ধারণ করতে পারি:
d = sqrt(h*h - r*r)
theta = arccos(r / h)
অবশেষে, বৃত্তটি ছেড়ে যাওয়ার এবং সোজা রেখার শুরু করার জন্য কী বিন্দু Qটি বের করার জন্য আমাদের মোট কোণটি + জানতে হবে এবং পি থেকে গন্তব্য পর্যন্ত সহজেই কোণ হিসাবে নির্ধারিত হয়েছে:
phi = arctan(dy / dx) [offset to the correct quadrant]
Q.x = P.x + r * cos(phi + theta)
Q.y = P.y + r * sin(phi + theta)
উপরের গণনাগুলি ডান-মোড়ের পথে উপস্থাপন করে। বাম-হাতের পথটি ঠিক একইভাবে গণনা করা যায়, ব্যতীত আমরা কোণ-টোপি গণনা করার জন্য 90_ আরম্ভের_নির্দেশ যোগ করি এবং পরে আমরা ব্যবহার করি - পরিবর্তে +। উভয় গণনা করার পরে, আমরা সহজেই দেখি যে কোন পথটি ছোট and
আমাদের এই অ্যালগরিদম এবং এর পরে অনুসরণকারীগুলির বাস্তবায়নে আমরা একটি ডেটা স্ট্রাকচার ব্যবহার করি যা চারটি স্বতন্ত্র "লাইন বিভাগ" সংরক্ষণ করে, যার প্রত্যেকে প্রত্যক্ষ হয় বা বাঁকা। এখানে বর্ণিত বাঁকা পথগুলির জন্য, কেবলমাত্র দুটি বিভাগ ব্যবহার করা হয়েছে: একটি খিলান একটি সরলরেখার পরে। ডেটা স্ট্রাকচারে এমন সদস্য রয়েছে যা সেগমেন্টটি একটি আর্ক বা একটি সরল রেখা, সেগমেন্টের দৈর্ঘ্য এবং তার সূচনা অবস্থান কিনা তা নির্দিষ্ট করে। বিভাগটি যদি একটি সরলরেখা হয় তবে ডেটা কাঠামোটি কোণটিও নির্দিষ্ট করে; আরাক্সের জন্য এটি বৃত্তের কেন্দ্র, বৃত্তের প্রারম্ভিক কোণ এবং আর্ক দ্বারা আবৃত মোট রেডিয়ান নির্দিষ্ট করে।
একবার আমরা দুটি পয়েন্টের মধ্যে পৌঁছানোর জন্য প্রয়োজনীয় বাঁকা পথটি গণনা করি, তবে তালিকা 2-তে দেখানো হয়েছে যে আমরা যেকোন সময় তাত্ক্ষণিকভাবে আমাদের অবস্থান এবং দিকটি সহজেই গণনা করতে পারি।
তালিকা 2. একটি নির্দিষ্ট সময়ে অবস্থান এবং ওরিয়েন্টেশন গণনা।
distance = unit_speed * elapsed_time
loop i = 0 to 3:
if (distance < LineSegment[i].length)
// Unit is somewhere on this line segment
if LineSegment[i] is an arc
//determine current angle on arc (theta) by adding or
//subtracting (distance / r) to the starting angle
//depending on whether turning to the left or right
position.x = LineSegment[i].center.x + r*cos(theta)
position.y = LineSegment[i].center.y + r*sin(theta)
//determine current direction (direction) by adding or
//subtracting 90 to theta, depending on left/right
else
position.x = LineSegment[i].start.x
+ distance * cos(LineSegment[i].line_angle)
position.y = LineSegment[i].start.y
+ distance * sin(LineSegment[i].line_angle)
direction = theta
break out of loop
else
distance = distance - LineSegment[i].length