সীমিত ত্বরণ সহ আমি কীভাবে অবজেক্টগুলির জন্য পাথ গণনা করব?


9

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

ডকুমেন্টেশনের একটি পয়েন্টার (বা এমনকি একটি নাম) পুরোপুরি ঠিক হয়ে যাবে - আমার কিছুতেই খুঁজে পেতে সমস্যা হচ্ছে।

আমার প্রচেষ্টায়, তারা সাধারণ ক্ষেত্রে কাজ করে তবে পয়েন্ট বি ন্যূনতম টার্নিংয়ের ব্যাসার্ধের তুলনায় যখন বিন্দু বি এর কাছাকাছি হয় এমন পরিস্থিতিতে খারাপভাবে ব্যর্থ হয়।

উদাহরণস্বরূপ, আপনি কীভাবে এই (সাহসী পথ) এর অনুরূপ কোনও পথ নির্ধারণ করবেন:

উদাহরণস্বরূপ উদ্দেশ্যে কেবল একটি বাঁকা পথ

সম্পাদনা করুন: আমার আসল সমস্যায়, কিছু সহজ পথের বাধা আছে, তবে আমার কাছে ইতিমধ্যে স্থানে একটি * অ্যালগোরিদম রয়েছে যা কাজ করে তবে এটি জিনিসগুলিকে তাত্ক্ষণিকভাবে শিরোনাম পরিবর্তন করতে দেয়, তাই গাড়িটি হঠাৎ 90% টার্ন করার মতো নির্বোধ মনে হয় looks যখন তারা একটি টার্ন পয়েন্টে আসে তখন একটি ডাইমে।


গেমদেব.স্ট্যাকেক্সেঞ্জার / প্রশ্নগুলি / ৮৮৮৮৮১/২ তবে আমি কীভাবে 3 ডি স্পেস সেট আপ করব সে সম্পর্কে উত্তরটি বুঝতে পেরেছি তা নিশ্চিত নই
xaxxon

"আদর্শভাবে এই অ্যালগরিদম পরিবর্তনশীল গতির সাথে মোকাবেলা করতে সক্ষম হবে" নূন্যতম বাঁক ব্যাসার্ধটি যে গতির সাথে পরিবর্তিত হয় তার সাথে কি মোটামুটি সম্পর্কিত, বা এটি কোনও একটি গাড়ীের জন্য স্থির?
ডিএমগ্রিগরি

আমি সেই অংশটি মুছব। আমি যা করছি তার জন্য এটি "গ্রান ট্যুরিস্টো" এর চেয়ে বেশি "সিম সিটি"। আপনি কেন এটি জিজ্ঞাসা করছেন তা আমি বুঝতে পেরেছি এবং আমি এটি যুক্ত করার পরে আমি কী ভাবছিলাম তা নিশ্চিত নই, কারণ আমি বুঝতে পারি যে এটি অপ্রাসঙ্গিক।
xaxxon

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

উত্তর:


7

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

চেনাশোনাযুক্ত একটি গাড়ি তার বাঁক ব্যাসার্ধ নির্দেশ করে। ( কেনে দিয়ে গাড়ী আইকন )

যে কোনও প্রারম্ভিক বিন্দু এবং দিকনির্দেশ থেকে, আমরা আমাদের সর্বনিম্ন বাঁক ব্যাসার্ধের সাথে দুটি বৃত্ত আঁকতে পারি - একটি বাম দিকে, একটি ডানদিকে। এগুলি আমাদের পথের সবচেয়ে সম্ভবতম সূচনার পয়েন্টগুলি বর্ণনা করে।

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

এখন সমস্যাটি এমন একটি পথ সন্ধান করতে হ্রাস করে যা প্রারম্ভের চেনাশোনাগুলির মধ্যে একটির সাথে শেষ চেনাশোনাগুলির একটিতে যোগ দেয়, প্রতিটিটিকে তার স্পর্শক বরাবর চুম্বন করে।

(এটি ধরে নেওয়া হচ্ছে যে আমাদের মাঝে মধ্যে বাধাগুলি খুঁজে পাওয়ার দরকার নেই, যা প্রশ্নের মধ্যে উল্লেখ করা হয়নি St স্টর্মউইন্ডের উত্তরটি এই ধরণের সমস্যার জন্য আমরা কীভাবে নেভিগেশন গ্রাফের তথ্য ব্যবহার করতে পারি তা জানতে পারে Once একবার আমাদের নোডগুলির ক্রম হয় পাস করার জন্য, আমরা পরিকল্পনার প্রতিটি বিভাগে নীচের পদ্ধতিটি প্রয়োগ করতে পারি))

যদি, সরলতার জন্য, আমরা সরল রেখা ব্যবহার করি, আমরা এরকম কিছু পাই:

একটি গাড়ি নিতে পারে এমন বিভিন্ন পথ দেখায় ডায়াগ্রাম।

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

এই পাথগুলি গণনা করা হচ্ছে

আসুন এক মোড় ঘুরিয়ে দেওয়ার জন্য কেসগুলি কার্যকর করা - বলুন আমরা ডান দিকে ঘুরিয়ে আমাদের পথ শুরু করি।

আমাদের ডানদিকে ঘুরিয়ে দেওয়ার কেন্দ্রটি হ'ল:

startRightCenter = carStart.position + carStart.right * minRadius

আসুন আমাদের পথের সরল বিভাগের কোণটি কল করুন (ধনাত্মক এক্স-অক্ষ থেকে মাপা) pathAngle

যদি আমরা কোনও ভেক্টরকে rightCenterসেই বিন্দু থেকে আঁকি যেখানে আমরা টার্নিং বৃত্তটি ছেড়ে চলেছি (কোন বিন্দুতে আমাদের অবশ্যই পথআঙ্গলের মুখোমুখি হতে হবে), তবে সেই ভেক্টরটি ...

startOffset = minRadius * (-cos(pathAngle), sin(pathAngle))

তার মানে আমরা যে বিন্দুতে বৃত্তটি রেখেছি তা অবশ্যই হওয়া উচিত ...

departure = startRightCenter + startOffset

আমরা যে মোড়কে আবার ঘুরিয়ে নিয়েছি সেটির উপরে নির্ভর করে আমরা বামে বা ডানদিকে ঘুরতে চাইছি কিনা তার উপর:

// To end with a right turn:
reentry = endRightCenter + startOffset

// To end with a left turn: (crossover)
reentry = endLeftCenter - startOffset

এখন, আমরা যদি আমাদের কাজটি সঠিকভাবে করে ফেলেছি তবে লাইনটিতে যোগদানের departureজন্য reentryলম্ব হওয়া উচিত startOffset:

dot(reentry - departure,  startOffset) = 0

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

আসুন উদাহরণ হিসাবে ডান টার্ন থেকে ডান ঘুরিয়ে যাওয়া কেসটিকে প্রতিস্থাপন করুন:

dot(endRightCenter + startOffset - startRightCenter - startOffset, startOffset) = 0
dot(endRightCenter - startRightCenter, startOffset) = 0
pathAngle = atan2(endRightCenter - startRightCenter)

ক্রসওভার কেস আরও জটিল - এটি এখনও আমি সমস্ত গণিতের জন্য কাজ করি নি। আমি এখনই ছাড়াই উত্তর পোস্ট করব, যদি বাকী বিবরণগুলি নিয়ে কাজ করি তবে এটি আপনার পক্ষে কার্যকর useful

সম্পাদনা করুন: সর্বনিম্ন বাঁক ব্যাসার্ধের ভিতরে গন্তব্য

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

নিকটস্থ গন্তব্যস্থলে পাথ-পরিকল্পনা করার সময় বিকল্পগুলি প্রদর্শন করে।

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


এটি সম্পর্কে চিন্তা করার এক দুর্দান্ত সহজ উপায় এবং চেনাশোনাগুলিতে স্পর্শকাতর কাজগুলি বেশ সহজ। আমি কেবল আপনার উত্তরটি এতদূর এড়িয়ে গিয়েছি, তবে প্রতিটি সমস্যা আমি গ্রহণ করেছি এমন একটি সমস্যা হ'ল যদি লক্ষ্যটি পয়েন্টের টার্নিং সার্কেলের মধ্যে থাকে।
xaxxon

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

2
এক মাস (এবং কয়েকটি বিভ্রান্তি) পরে আমি এই কাজটি পেয়েছি। আমি 4 টি স্পর্শীকরণ গণনা করি - "বাহ্যিক" এবং "অভ্যন্তরীণ" (বা "ক্রসিং") স্পর্শকাতর। সুতরাং start.left_circ to goal.left_c বৃত্ত, start.left_c বৃত্তটি "ক্রসিং" কে লক্ষ্য.সাইট_ সার্কেল (এবং অন্য দুটি মাত্র চেনাশোনাগুলি স্যুইচ করছে)। এখানে একটি "বহিরাগত" পথ: youtube.com/watch?v=99e5Wm8OKb0 এবং এখানে একটি "ক্রসিং" পথ রয়েছে: youtube.com/watch?v=iEMt8mBheZU
xaxxon

1

এটি নেভিগেশনের জন্য আপনার ডেটা মডেলের বাকী অংশের উপর নির্ভর করে। অর্থাৎ। আপনার কী ডেটা সহজলভ্য, আপনি কীভাবে সহজে ডেটা যুক্ত করতে পারেন এবং কীভাবে আপনি এটি ব্যবহার করেন।

পানিতে ট্র্যাফিক সিস্টেম থেকে একইরকম দৃশ্য গ্রহণ করা এবং এটি অনুমানের সাথে

  • আপনি একটি খেলা লুপ হয়
  • আপনার একটি নোড পাথ সিস্টেম আছে
  • আপনার গাড়িগুলি একটি স্বায়ত্তশাসিত বস্তুর মতো আচরণ করে যা নিজের শক্তি এবং স্টিয়ারিং ব্যবহার করে "ভিতরে থেকে" নিজেকে নিয়ন্ত্রণ করে
  • আপনার গাড়িগুলি রেলের মতো চলাচল করে না

আপনার নীচের মতো কিছু থাকতে পারে (ছবিগুলির শিশুসুলভ উপস্থিতির জন্য আমাকে ক্ষমা করুন)

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

(লাল স্কোয়ারগুলি নোড, লাল রেখাগুলি নোড আন্তঃসংযোগ। ধরে নিও যে আপনি কোনও প্যাথফাইন্ডিং সলভার ব্যবহার করেছেন যা ছবিতে দেখানো নোডগুলি 1-9 দিয়েছিল; নোড 4-9 এবং আপনি সবুজ লাইন দ্বারা নির্দেশিত নোডগুলি দিয়ে যেতে চান , নোড # 9 এর গ্যারেজে; তবে আপনি গ্রিন লাইনে অবিকল যেতে চান না, পরিবর্তে ডান পাশের লেনে স্বাভাবিকভাবেই থাকুন এবং মসৃণ ম্যানুভারগুলি করুন)।

প্রতিটি নোডে মেটাডেটা থাকে যা উদাহরণস্বরূপ ব্যাসার্ধ বা একাধিকগুলি বিভিন্ন উদ্দেশ্যে রাখে। তার মধ্যে একটি হল নীল বৃত্ত, যা গাড়িগুলির জন্য লক্ষ্য নির্দেশিকা সরবরাহ করে

যে কোনও অনুষ্ঠানে , গাড়ির পরবর্তী দুটি নোড পয়েন্ট P (পরের) এবং পি (পরের + 1), এবং তাদের অবস্থান সম্পর্কে সচেতন হওয়া দরকার । স্বাভাবিকভাবেই, গাড়ীটিরও একটি অবস্থান রয়েছে। একটি গাড়ী লক্ষ্য করে পি এর নীল মেটাডেটা-বৃত্তের ডান পাশের স্পর্শক (পরবর্তী)। সুতরাং গাড়িগুলি বিপরীত দিকে যাবেন, সুতরাং তাদের সংঘর্ষ হবে না। স্পর্শকাতর লক্ষ্য করার অর্থ গাড়িটি কোনও দিক থেকে বৃত্তের কাছে যেতে পারে এবং সর্বদা সঠিক থাকে। এটি একটি মোটামুটি মূল নীতি, এটি বিভিন্ন উপায়ে উন্নত করা যেতে পারে।

একটি দূরত্ব নির্ধারণের জন্য পি (পরের + 1) প্রয়োজন - কারন পি (পরের) এ পৌঁছেছে বা এর মেটাডাটার কিছু ব্যাসার্ধের ভিতরে চলে গেছে, এটি পি (পরের + 1) কত দূরে রয়েছে তার উপর নির্ভর করে এটি স্টিয়ারিং কোণটি সামঞ্জস্য করতে পারে । অর্থাৎ। যদি এটি কাছে থাকে তবে অনেকটা ঘুরিয়ে দিন, যদি এটি খুব দূরে থাকে তবে সামান্য ঘুরুন। স্পষ্টতই অন্যান্য নিয়ম এবং প্রান্তের শর্তাদিও হওয়া দরকার, উদাহরণস্বরূপ গাড়ি এবং পি এর (পরবর্তী) এবং পি (পরের + 1) এর ডান পাশের স্পর্শগুলির উপর ভিত্তি করে একটি সহায়তা লাইনের মধ্যকার দূরত্ব গণনা, এবং তার দ্বারা সংশোধন - ড্যাশযুক্ত (উপরে ছবি) এবং বিন্দুযুক্ত (পিকের নীচে) লাইনে থাকার জন্য একটি উইল।

যাই হোক না কেন, গাড়িটি একটি নোড পেরিয়ে যাওয়ার সাথে সাথে এটি তা ভুলে যায় এবং পরবর্তী দুটিটি দেখতে শুরু করে

আপনার প্রশ্ন। স্পষ্টতই, নোড 7 এ পৌঁছানোর সময় (উপরের ছবিতে, নীচের ছবিতে নোড 2 হিসাবে দেখা হয়েছে), এটি যথেষ্ট পরিণত হতে পারে না

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

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

সবুজ সহায়তার লাইনগুলি 1,2,3 রাখুন । গাড়িটি ম্যাজেন্টা বৃত্তে পৌঁছানোর সাথে সাথে এটি ডানদিকে ঘুরতে শুরু করে। এই মুহুর্তে, আপনি ইতিমধ্যে গণনা করতে পারেন যে এটি সফল হবে না (আপনি সর্বাধিক টার্নের হার জানেন এবং বক্ররেখার গণনা করতে পারেন, এবং দেখতে পারেন যে এটি হেল্পলাইন 2 এবং 3 উভয় অতিক্রম করবে)। স্টিয়ারিং পুরো ডানদিকে ঘুরুন এবং এটিকে এগিয়ে চলুন (পদার্থবিজ্ঞানের বর্ধনের সাহায্যে) এবং সহায়তা লাইন 3 এ পৌঁছানোর সাথে সাথে এটি ধীরে ধীরে (প্রান্তিকের কাছাকাছি - চ (হেল্পলাইনে ব্যবহার করতে হবে ইত্যাদি)) চালিয়ে দিন। যখন এটা সাহায্যের লাইন 3, ঢোকা বিপরীত , মোডে স্টিয়ারিং ঘুরিয়ে পূর্ণ বিপরীতসাহায্যের লাইন 4 এ না আসা পর্যন্ত এটি বিপরীত হতে দিন(নোড 1 এবং 2 এর মধ্যে সংযোগ লাইন - "লাইনের অ্যালগরিদমের পাশে পয়েন্ট" এর জন্য গুগল)। ধীরে ধীরে, এটি পৌঁছানোর সাথে সাথে, আবার ড্রাইভের সামনে মোডে যান , চাকাটি ঘুরিয়ে দিন। রাস্তা পরিষ্কার না হওয়া পর্যন্ত পুনরাবৃত্তি করুন - দৃশ্যত এটি এবার অতিরিক্ত 1 জন ম্যানুভারের সাথে যথেষ্ট ছিল।

এটি সাধারণ ধারণা: গেম লুপের সময়, বা গেমস টাস্ক কুই সিস্টেমটি পরীক্ষা করার সময়:

  • বর্তমান প্রান্তের সীমা এবং লক্ষ্যের বিপরীতে গাড়ির অবস্থান, গতি, কোণ ইত্যাদি পরীক্ষা করুন ,
  • যদি এখনো পৌঁছাতে পারেনি , তুমি কি করছিলে চালিয়ে (দিন পদার্থবিদ্যা এটিকে সরান; গাড়ী একটি RPM এবং একটি গিয়ার আছে)। উদাহরণস্বরূপ ০.০ এস এর ক্ষেত্রে আপনার কুই সিস্টেমে একটি নতুন চেক .োকান।
  • যদি পৌঁছে যায় , নতুন শর্তগুলি ক্যালক্কুলেট করুন , ডেটা সেট করুন এবং শুরু করুন । উদাহরণস্বরূপ ০.০ এস এর জন্য কুই সিস্টেমে নতুন চেক প্রবেশ করান s
  • লুপ চক্রটি সম্পূর্ণ করুন - চালিয়ে যান, পুনরাবৃত্তি করুন।

নোড এবং গাড়িগুলিকে সাশ্রয়ী মূল্যের ডেটা দেওয়ার মাধ্যমে, চলাচল এবং ধারাবাহিকতা থাকবে।

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


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

এলোমেলোভাবে, আসলে আপনি যা বর্ণনা করেছেন তার কাছে আমার কাছে কিছুটা কাছে রয়েছে। বেগুনি "চলমান" রেখাটি দুটি সম্পূর্ণ লাইন থেকে সম্পূর্ণ প্রক্রিয়াগতভাবে উত্পন্ন হয়: youtube.com/watch?v=EhhhhrkmRiY তবে এটি "আঁটসাঁটা" পরিস্থিতিতে কাজ করে না এবং বাঁকটি সত্যিকারের পথে চলার জন্য ব্যবহৃত হয় না।
xaxxon

0

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

bool Circle::outer_tangent_to(const Circle & c2, LineSegment & shared_tangent) const {
    if (this->direction != c2.direction) {
        return false;
    }
    if (this->radius != c2.radius) {
        // how to add it: http://mathworld.wolfram.com/Circle-CircleTangents.html
        // just subtract smaller circle radius from larger circle radius and find path to center
        //  then add back in the rest of the larger circle radius
        throw ApbException("circles with different length radius not supported");
    }

    auto vector_to_c2 = c2.center - this->center;
    glm::vec2 normal_to_c2;
    if (this->direction == Circle::CW) {
        normal_to_c2 = glm::normalize(glm::vec2(-vector_to_c2.y, vector_to_c2.x));
    } else {
        normal_to_c2 = glm::normalize(glm::vec2(vector_to_c2.y, -vector_to_c2.x));
    }

    shared_tangent = LineSegment(this->center + (normal_to_c2 * this->radius),
                                 c2.center + (normal_to_c2 * this->radius));
    return true;
}


bool Circle::inner_tangent_to(const Circle & c2, LineSegment & tangent) const {

    if (this->radius != c2.radius) {
        // http://mathworld.wolfram.com/Circle-CircleTangents.html
        // adding this is non-trivial
        throw ApbException("inner_tangents doesn't support circles with different radiuses");
    }

    if (this->direction == c2.direction) {
        // inner tangents require opposing direction circles
        return false;
    }

    auto vector_to_c2 = c2.center - this->center;
    auto distance_between_circles = glm::length(vector_to_c2);

    if ( distance_between_circles < 2 * this->radius) {
//      throw ApbException("Circles are too close and don't have inner tangents");
        return false;
    } else {
        auto normalized_to_c2 = glm::normalize(vector_to_c2);
        auto distance_to_midpoint = glm::length(vector_to_c2) / 2;
        auto midpoint = this->center + (vector_to_c2 / 2.0f);

        // if hypotenuse is oo then cos_angle = 0 and angle = 90˚
        // if hypotenuse is radius then cos_angle = r/r = 1 and angle = 0
        auto cos_angle = radius / distance_to_midpoint;
        auto angle = acosf(cos_angle);

        // now find the angle between the circles
        auto midpoint_angle = glm::orientedAngle(glm::vec2(1, 0), normalized_to_c2);

        glm::vec2 p1;
        if (this->direction == Circle::CW) {
            p1 = this->center + (glm::vec2{cos(midpoint_angle + angle), sin(midpoint_angle + angle)} * this->radius);
        } else {
            p1 = this->center + (glm::vec2{cos(midpoint_angle - angle), sin(midpoint_angle - angle)} * this->radius);
        }

        auto tangent_to_midpoint = midpoint - p1;
        auto p2 = p1 + (2.0f * tangent_to_midpoint);
        tangent = {p1, p2};

        return true;
    }
};

এখানে কর্মের উপরে দুটি কোডের সিনেমা রয়েছে:

এখানে একটি "বাহ্যিক" পথ: http://youtube.com/watch?v=99e5Wm8OKb0 এবং এখানে একটি "ক্রসিং" পথ রয়েছে: http://youtube.com/watch?v=iEMt8mBheZU

এই কোডটি যদি সহায়তা করে তবে আপনার এখানে কিছু অংশের অংশ সম্পর্কে প্রশ্ন রয়েছে, কেবল একটি মন্তব্য পোস্ট করুন এবং আমার দু'এক দিনের মধ্যে এটি দেখতে হবে।

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