سؤال

أحتاج إلى خوارزمية لمعرفة ما إذا كانت زاوية واحدة ضمن كمية معينة من الدرجات من زاوية أخرى.

فكرتي الأولى كانت (a-x < b) && (a+x > b), ، لكنها تفشل عندما يتعين عليها العمل بزوايا تتجول من -179 إلى 180.

في الرسم البياني أعلاه ، يجب أن تكون المنطقة (الخضراء) التي يجب أن تكون الزاوية بين اللف بين الجوانب السلبية والإيجابية. كيف يمكنني تحديد ما إذا كانت الزاوية (الخط الأحمر) تقع داخل هذه المنطقة؟

هل كانت مفيدة؟

المحلول

جرب هذه الصيغة:

360-(|a-b|)%360<x || (|a-b|)%360<x

أو، في PHP:

<?php

$b = 10;
$angle1 = -179;
$angle2 = 180;

$diff = $angle1 - $angle2;
if(abs($diff % 360) <= $b || (360-abs($diff % 360))<=$b) {
  echo "yes";
} else {
  echo "no";
}

?>

نصائح أخرى

كما يشير مارسيل بحق ، من المحتمل أن يكون Modulo على الأرقام السلبية مشكلة. أيضا ، ما هو الفرق بين 355 و 5 درجات؟ قد يكون الأمر كذلك ليكون 350 درجة ولكن 10 درجات ربما ما يتوقعه الناس. يمكننا أن نجعل من الافتراضات التالية:

  1. نريد أصغر زاوية إيجابية بين زاويتين أخريين هكذا 0 <= diff <= 180;
  2. نحن نعمل بدرجات. إذا راديان ، استبدل 360 2*PI;
  3. يمكن أن تكون الزوايا إيجابية أو سلبية يمكن أن تكون خارج النطاق -360 < x < 360 حيث x هي زاوية إدخال و
  4. ترتيب زوايا الإدخال أو اتجاه الفرق غير ذي صلة.

المدخلات: الزوايا A و B. لذا فإن الخوارزمية هي ببساطة:

  1. تطبيع A و B إلى 0 <= x < 360;
  2. حساب أقصر زاوية بين الزاويتين العاديين.

بالنسبة للخطوة الأولى ، لتحويل الزاوية إلى النطاق المطلوب ، هناك احتمالان:

  • x >= 0: عادي = x ٪ 360
  • x < 0: عادي = (-x / 360 + 1) * 360 + x

والثاني مصمم لإزالة أي غموض على الفرق في تفسير عمليات المعامل السلبية. لإعطاء مثال يعمل لـ x = -400:

  -x / 360 + 1
= -(-400) / 360 + 1
= 400 / 360 + 1
= 1 + 1
= 2

من ثم

normal = 2 * 360 + (-400)
       = 320

لذلك بالنسبة للمدخلات 10 و -400 الزوايا العادية هي 10 و 320.

الآن نحسب أقصر زاوية بينهما. كتحقق من العقل ، يجب أن يكون مجموع هاتين الزاويتين 360. في هذه الحالة ، تكون الاحتمالات 50 و 310 (ارسمها وسترى هذا). لعمل هذه:

normal1 = min(normal(a), normal(b))
normal2 = max(normal(a), normal(b))
angle1 = normal2 - normal1
angle2 = 360 + normal1 - normal2

لذلك على مثالنا:

normal1 = min(320, 10) = 10
normal2 = max(320, 10) = 320
angle1 = normal2 - normal1 = 320 - 10 = 310
angle2 = 360 + normal1 - normal2 = 360 + 10 - 320 = 50

سوف تلاحظ normal1 + normal2 = 360 (ويمكنك حتى إثبات أن هذا هو الحال إذا أردت).

أخيرا:

diff = min(normal1, normal2)

أو 50 في حالتنا.

بالنسبة لنصف قطر 1 ، فإن المسافة بين نقاط النهاية الخطية هي 2 -sin ((AB/2). لذا قم برمي 2 لأنك مهتم فقط بالمقارنة ، وقارن الخطيئة (x/2) مع SIN ((AB)/ 2). وظائف المثلثات تهتم بكل الغلاف.

يمكنك أيضًا استخدام منتج DOT:

cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)

تنفيذ C ++:

float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
                 360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top