سؤال

نظرا لزوايا في النطاق - PI -> PI حول الإحداثيات، ما هي قيمة أصغر الزوايا بينهما؟

مع الأخذ في الاعتبار أن الفرق بين PI و PI ليس 2 بي ولكن صفر.

مثال:

تخيل دائرة، مع سطرين يخرجان من المركز، هناك زوايا بين تلك الخطوط، الزاوية التي يصنعونها في الداخل زاوية أصغر, ، والزاوية التي يصنعونها في الخارج، ويعرف أيضا باسم الزاوية الأكبر. كلا الزوايا عند إضافتها تصنع دائرة كاملة. بالنظر إلى أن كل زاوية يمكن أن تنسجم في نطاق معين، ما هي قيمة الزوايا الأصغر، مع مراعاة التمديد

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

المحلول

هذا يعطي زاوية موقعة لأي زوايا:

a = targetA - sourceA
a = (a + 180) % 360 - 180

احذر في العديد من اللغات modulo تقوم العملية بإرجاع قيمة مع نفس الإشارة كأصل (مثل C، C ++، C #، JavaScript، القائمة الكاملة هنا). هذا يتطلب مخصص mod وظيفة مثل ذلك:

mod = (a, n) -> a - floor(a/n) * n

أو هكذا:

mod = (a, n) -> (a % n + n) % n

إذا كانت الزوايا داخل [-180، 180] هذا يعمل أيضا:

a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0

بطريقة أكثر سرعة:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180

نصائح أخرى

X هي الزاوية الهدف. ذ هو المصدر أو الزاوية البدء:

atan2(sin(x-y), cos(x-y))

إرجاع زاوية دلتا الموقع. لاحظ أنه وفقا ل API الخاص بك قد يكون ترتيب معلمات وظيفة ATAN2 () مختلفا.

إذا كانت زواياك X و Y، فستكون إحدى الزوايا بينها عبارة عن ABS (X - Y). الزاوية الأخرى هي (2 * PI) - ABS (X - Y). لذلك قيمة أصغر الزوايا 2 هي:

min((2 * PI) - abs(x - y), abs(x - y))

يمنحك هذا القيمة المطلقة للزاوية، ويفترض أن المدخلات تطبيعها (أي: داخل النطاق [0, 2π)).

إذا كنت ترغب في الحفاظ على علامة (أي: الاتجاه) من الزاوية وأيضا قبول الزوايا خارج النطاق [0, 2π) يمكنك تعميم ما سبق. إليك رمز بيثون للإصدار المعمم:

PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
    a = (x - y) % TAU
    b = (y - x) % TAU
    return -a if a < b else b

نلاحظ أن % لا يتصرف المشغل بنفس الشيء في جميع اللغات، خاصة عندما تشارك القيم السلبية، لذلك إذا كانت تقوم بتنفيذ بعض التعديلات بالتوقيع ضرورية.

ارتفع إلى التحدي المتمثل في توفير الإجابة الموقعة:

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)

بالنسبة لمستخدمي UnityEngine، الطريقة السهلة هي فقط للاستخدام mathf.deltaangle..

الحل الحسابي (على عكس الخوارزميات)

angle = Pi - abs(abs(a1 - a2) - Pi);

ليست هناك حاجة لحساب وظائف المثلثية. الرمز البسيط في لغة C هو:

#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;

arg = fmod(y-x, PIV2);
if (arg < 0 )  arg  = arg + PIV2;
if (arg > M_PI) arg  = arg - PIV2;

return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 )  arg  = arg + C360;
if (arg > 180) arg  = arg - C360;
return (-arg);
}

دع فرمفا = أ - ب، في راديان

dif = difangrad(a,b);

دع فرمفا = أ - ب، بدرجات

dif = difangdeg(a,b);

difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000

لا خطيئة، لا كوس، لا تان، .... هندسة فقط!

رمز فعال في C ++ هو:

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI or 180;
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top