আমি কীভাবে দুটি 2 ডি ভেক্টরগুলির মধ্যে কোণ এবং যথাযথ টার্নের দিক গণনা করতে পারি?


26

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

আমি সূত্রটি ব্যবহার করে এই দুটি ভেক্টরের মধ্যবর্তী কোণটি গণনা করছি

arccos((v · w) / (|v| · |w|))

আমার যে সমস্যাটি হচ্ছে তা হ'ল arccosকেবল 0 ° এবং 180 between এর মধ্যে মানগুলি দেয় ° এটি অন্য জাহাজের মুখোমুখি আমার বাম বা ডানদিকে ঘুরতে হবে কিনা তা নির্ধারণ করা অসম্ভব করে তোলে।

এই কাজ করতে একটি ভাল উপায় আছে কি?


1
আপনি যদি ityক্য ব্যবহার করছেন তবে চেক আউট করুন Mathf.DeltaAngle()
রাসেল বোরোগোভ

উত্তর:


22

এটি একটি 2 ডি ক্রস-পণ্য ব্যবহার করা আরও দ্রুত। কোনও ব্যয়বহুল ট্রিগ ফাংশন জড়িত নেই।

b2Vec2 target( ... );
b2Vec2 heading( ... );

float cross = b2Cross( target, heading );

if( cross == -0.0f )
   // turn around

if( cross == 0.0f )
  // already traveling the right direction

if( cross < 0.0f)
  // turn left

if( cross > 0.0f)
  // turn right

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

b2Vec2 A(...);
b2Vec2 B(...);

float angle_A = std::atan2(A.y,A.x);
float angle_B = B.GetAngle(); // Box2D already figured this out for you.

float angle_from_A_to_B = angle_B-angle_A;
float angle_from_B_to_A = angle_A-angle_B;

1
@ টেট্রাডের উত্তরটি পড়ার পরে আমি মনে করি আপনি একটি ক্রস পণ্য এবং একটি সংহত করতে পারেন arccos। এইভাবে আপনি কেবল একটি ট্রিগ ফাংশন ব্যবহার করবেন তবে এখনও প্রকৃত কোণ রয়েছে। তবে আমি এই অপ্টিমাইজেশনের বিরুদ্ধে প্রস্তাব দিচ্ছি যতক্ষণ না আপনি নিশ্চিত হন যে আপনি এআই অ্যাঙ্গেল ট্র্যাকিং আপনার গেমের পারফরম্যান্সের উপর লক্ষণীয় প্রভাব ফেলছে।
deft_code

2
হ্যাঁ, ভেক্টর এবং কোণগুলির মধ্যে রূপান্তর করার সময়, atan2 () অবশ্যই আপনার বন্ধু।
bluescrn

1
ধন্যবাদ! আমি খুঁজে পেয়েছি যে আসলে আমার কোণটির দরকার নেই, 2 ডি ক্রস পণ্যটি ধরা আমার প্রয়োজনের পক্ষে সহজ।
ত্রুটি 454

2
এছাড়াও আপনার if( cross == -0.0f )বনাম if( cross == 0.0f )চেকটি অত্যন্ত ভঙ্গুর দেখাচ্ছে।
bobobobo

1
@ বোবোবো, একটি পদার্থবিজ্ঞানের ইঞ্জিন সহ এটি কেবল কোনও দিক বাছাই এবং সরিয়ে নেওয়া কোনও বিকল্প হতে পারে না। ম্যাজিকালি বাঁক ফিজিক ইঞ্জিনগুলি ফ্রিক আউট করতে পারে। আরও যাদুতে ঘোরানো অ্যানিমেশনের জন্যও ভয়ঙ্কর দেখাচ্ছে। সুতরাং হ্যাঁ, আপনি বাম বা ডান ধারণা ছাড়া এটি সমাধান করতে পারেন , তবে একটি পালিশ সমাধানের জন্য প্রায়শই এগুলির প্রয়োজন হয়।
deft_code

10

2 ডি ক্রস পণ্য (যেমন ক্রস পণ্য ভেক্টরের z উপাদান) এর আরকসিন ব্যবহার করুন। এটি আপনাকে 90-90 দিবে যা আপনাকে বাম বা ডানে যেতে হবে তা জানাতে দেবে।

সাবধান হন কারণ একটি ক্রস বি বি ক্রস এ এর ​​সমান নয় as

আরেকটি কৌশল (তবে সম্ভবত ততটা সোজা নয়) হ'ল atan2 ব্যবহার করে দুটি ভেক্টরের "শিরোনাম" গণনা করা এবং তারপরে এক্স ডিগ্রিটি নির্দেশককে y ডিগ্রিতে B নির্দেশ করে বামে বা ডান দিকে যেতে হবে কিনা তা নির্ধারণ করা।


প্রতিক্রিয়ার জন্য আপনাকে ধন্যবাদ. ভবিষ্যতের ব্রাউজারগুলির জন্য পরিষ্কার হওয়ার জন্য, 2 ডি ক্রস পণ্যটির মাত্রার বিপরীত সাইন নেওয়া 0 এবং 90 এর মধ্যে মান দেয় the 2 ডি ক্রস প্রোডাক্টের জেড-উপাদানটির সাইন নিলে কাঙ্ক্ষিত ফলাফল পাওয়া যায়।
ত্রুটি 454

@ এরর ৪৫৪, আপনি একেবারে ঠিক বলেছেন, আমার পোস্ট স্থির করেছেন।
টেট্রাড

1

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

ভেক্টর w(শিপ 1 থেকে শিপ 2 পর্যন্ত ভেক্টর) আপনার প্রয়োজনীয় সমস্ত তথ্য। এর ভারিত সংস্করণ ব্যবহার করে শিপ 1 এর বেগ ভেক্টর বা শিপ 1 এর ত্বরণ ভেক্টর (অথবা সরাসরি শিরোনাম ভেক্টর) উভয়ই সংশোধন করুন w

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

জাহাজ 1 কত দূরে কোর্সটি বন্ধ রয়েছে তার দৈর্ঘ্য (কীভাবে v এর সাথে w এর সাথে মেলে না) ব্যবহার করে ( 1 - dot(v,w)) ব্যবহার করা যাবে

  • ( dot(v,w)যখন সর্বাধিক হয় vএবং wঠিক ঠিক লাইনে থাকে)
  • ( 1 - dot(v,w)) 0 দেয় যখন vএবং wসম্পূর্ণরূপে প্রদত্ত আপ রেখাযুক্ত হয় vএবং wস্বাভাবিক হয়)

0

সাধারণ জ্যামিতির মাধ্যমে কোনও ভেক্টরের পরম কোণটি খুঁজে পাওয়ার সহজ উপায় রয়েছে।

উদাহরণস্বরূপ ভেক্টর ভি = 2 আই - 3 জ;

x সহগের পরম মান = 2;

y সহগের পরম মান = 3;

কোণ = আতান (2/3); [কোণ 0 থেকে 90 এর মধ্যে হবে]

চতুর্ভুজ কোণের ভিত্তিতে পরিবর্তন করা হবে।

যদি (x সহগ <0 এবং y সহগ> 0) তবে কোণ = 180-কোণ;

যদি (x সহগ <0 এবং y সহগ <0) তবে কোণ = 180 + কোণ;

যদি (x সহগ> 0 এবং y সহগ <0) তবে কোণ = 360-কোণ;

যদি (x সহগ> 0 এবং y সহগ> 0) তবে কোণ = কোণ;

প্রথম এবং দ্বিতীয় ভেক্টরের কোণ খুঁজে পাওয়ার পরে, কেবল দ্বিতীয় ভেক্টর থেকে প্রথম ভেক্টর কোণটি বিয়োগ করুন। তারপরে আপনি দুটি ভেক্টরের মধ্যে পরম কোণ পাবেন।


5
এটি আপনার জন্য atan2 () ফাংশন প্রয়োগ করে। :)
নাথান রিড

@ নাথানরিড, হ্যাঁ, তবে ট্রিগ ওভারহেড এড়াতে আপনি কোনও বিন্দু পণ্য দিয়ে এই পদ্ধতিটি ব্যবহার করতে পারবেন না?
jdk1.0

0

হয়তো আমার কিছুটা আলাদা প্রশ্ন পোস্ট করা উচিত এবং নিজেই এর উত্তর দেওয়া উচিত; এটি আমার কাছে থাকা সবচেয়ে কাছের প্রশ্নটি।

আমি এইচটিএমএল ক্যানভাসে 2D কাজ করছি, যেখানে আমার ভেক্টরের চেয়ে রেডিয়ানে ঘোরানো কোণ রয়েছে। "বর্তমান শিরোনাম" (এইচ) থেকে "টার্গেট শিরোনাম" (টি) এ যাওয়ার জন্য আমার "টার্ন এঙ্গেল" (টা) দরকার ছিল।

এখানে আমার সমাধান:

var ta = t - h,
    ata = Math.abs(ta)
;
if (ta > Math.PI) ta = (ta / ata) * (Math.PI - ata)
return ta;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.