سؤال

لدى Atan2 (Y، X) هذا التوقف عند 180 درجة حيث يتحول إلى -180 درجة ..0 درجة الذهاب في اتجاه عقارب الساعة.

كيف يمكنني تعيين مجموعة من القيم إلى 0 درجة ..360 درجة؟

هنا هو رمزي:

CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);

أنا أتحسين اتجاه حدث تمرير مستمر بالنظر إلى نقطة انطلاق ونقطة النهاية، كلا من هيكل نقاط XY. الرمز هو لجهاز iPhone ولكن أي لغة تدعم ATAN2F () ستفعل.

شكرا لمساعدتكم اللاعبين، مع الحلول العامة والرمز.

تحديث: لقد صنعت إجابة Erikkallen في وظيفة بأسماء متغيرة طويلة لطيفة، لذلك سوف أفهمها 6 أشهر من الآن. ربما سوف يساعد بعض iPhone noob الأخرى.

float PointPairToBearingDegrees(CGPoint startingPoint, CGPoint endingPoint)
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
    float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
    float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
    return bearingDegrees;
}
هل كانت مفيدة؟

المحلول

(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)

نصائح أخرى

حل باستخدام modulo.

حل بسيط يمسك جميع الحالات.

degrees = (degrees + 360) % 360;  // +360 for implementations where mod returns negative numbers

تفسير

إيجابية: 1 إلى 180

إذا قمت بتددي أي عدد إيجابي بين 1 و 180 بنسبة 360، فستحصل على نفس الرقم الذي تضعه بالضبط. وزارة الدفاع هنا تضمن إرجاع هذه الأرقام الإيجابية بنفس القيمة.

سلبي: -180 إلى -1

باستخدام MOD هنا سيعود القيم في حدود 180 و 359 درجة.

حالات خاصة: 0 و 360

باستخدام MOD يعني أنه تم إرجاع 0، مما يجعل هذا الحل الآمن 0-359 درجة.

فقط أضف 360 درجة إذا كانت الإجابة من Atan2 أقل من 0 درجة.

أو إذا كنت لا تحب المتفرعة، فقل فقط المعلمين وإضافة 180 درجة إلى الإجابة.

(إضافة 180 درجة إلى قيمة الإرجاع تضعها بشكل جيد في نطاق 0-360، ولكن تقلب الزاوية. ينقل كل من معلمات الإدخال تقلبها مرة أخرى.)

@ reikkallen هو قريب ولكن ليس صحيحا تماما.

theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);

يجب أن يعمل هذا في C ++: (اعتمادا على كيفية تنفيذ FMOD، فقد يكون الأمر أسرع أو أبطأ من التعبير الشرطي)

theta_deg = fmod(atan2(y,x)/M_PI*180,360);

بدلا من ذلك يمكنك القيام بذلك:

theta_deg = atan2(-y,-x)/M_PI*180 + 180;

منذ (x، y) و (-x، -y) تختلف في الزوايا بمقدار 180 درجة.

لدي 2 حلول يبدو أنها تعمل لجميع مجموعات x الإيجابية والسلبية x و y.

1) سوء المعاملة ATAN2 ()

وفقا للمستندات Atan2 يأخذ المعلمات Y و X في هذا النظام. ومع ذلك، إذا عكسها، فيمكنك القيام بما يلي:

double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
    degrees += 360; 
}

2) استخدم Atan2 () بشكل صحيح وتحويله بعد ذلك

double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
    degrees = 450 - degrees;
}
else
{
    degrees = 90 - degrees;
}

@ jason s: لن يعمل "FMOD" الخاص بك على تنفيذ متوافق مع المعايير. المعيار C واضح وواضح (7.12.10.1، "وظائف FMOD"):

إذا كانت y غير صفرة، فإن النتيجة لها نفس علامة X

هكذا،

fmod(atan2(y,x)/M_PI*180,360)

هو في الواقع مجرد إعادة كتابة حرفية من:

atan2(y,x)/M_PI*180

اقتراحك الثالث، ومع ذلك، هو المكان.

هذا هو ما أقوم به عادة:

float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
angle = Math.atan2(x,y)*180/Math.PI;

لقد صنعت صيغة لزاوية التوجيه إلى 0 إلى 360

angle + Math.ceil( -angle / 360 ) * 360;

حل بديل هو استخدام عصري () وظيفة محددة على النحو التالي:

function mod(a, b) {return a - Math.floor (a / b) * b;}

ثم، مع الوظيفة التالية، والزاوية بين INI (X، Y) و نهاية (X، Y) يتم الحصول على النقاط. يتم التعبير عن الزاوية في درجات تطبيعها إلى [0، 360]. والشمال الرجوع 360 درجة.

    function angleInDegrees(ini, end) {
        var radian = Math.atan2((end.y - ini.y), (end.x - ini.x));//radian [-PI,PI]
        return mod(radian * 180 / Math.PI + 90, 360);
    }

ستحسب الحزم R الجيوفير المحملات، وهو خط دائم ثابت بالنظر إلى نقطة الأصل وشرق / تورث. يجب أن يكون الشرق والورث في مصفوفة أو متجه. نقطة الأصل لارتفع الرياح هي 0،0. يبدو أن التعليمات البرمجية التالية حل المشكلة بسهولة:

windE<-wind$uasE
windN<-wind$vasN
wind_matrix<-cbind(windE, windN)
wind$wind_dir<-bearingRhumb(c(0,0), wind_matrix)
wind$wind_dir<-round(wind$wind_dir, 0)
theta_rad = Math.Atan2(y,x);
if(theta_rad < 0)
  theta_rad = theta_rad + 2 * Math.PI;    //if neg., add 2 PI to it
theta_deg = (theta_rad/M_PI*180) ;        //convert from radian to degree

//or
theta_rad = Math.Atan2(y,x);
theta_rad = (theta_rad < 0) ? theta_rad + 2 * Math.PI : theta_rad;
theta_deg = (theta_rad/M_PI*180) ;

-1 تصبح DEG (-1 + 360) = 359 درجة
-179 تصبح DEG (-179 + 360) = 181 درجة

double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

سيعود هذا إلى درجة من 0 درجة -360 درجة عكس عقارب الساعة، 0 درجة في الساعة الثالثة.

صيغة للحصول على مجموعة من القيم من 0 إلى 360 درجة.

f (x، y) = 180-90 * (علامة 1 + (x)) * (علامة 1 (y ^ 2)) - 45 * (2 + علامة (x)) * تسجيل (Y)

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top