سؤال

لدي مجموعة من نقاط البيانات في الفضاء ثلاثي الأبعاد والتي يبدو أنها تقع جميعها على مستوى معين.أستخدم PCA لحساب معلمات المستوى.يعطيني المكون الثالث من PCA المتجه الطبيعي للمستوى (أضعف مكون).

ما أريد فعله بعد ذلك هو تحويل جميع النقاط إلى المستوى المذكور وإلقاء نظرة عليها بشكل ثنائي الأبعاد.

كانت فكرتي هي القيام بما يلي:

  • ابحث عن نقطة مركزية (نقطة متوسطة) على المستوى
  • اطرحها من جميع نقاط البيانات لترتيبها حول الأصل
  • قم بتدوير العمودي بحيث يصبح (0,0,-1)
  • قم بتطبيق هذا التدوير على كافة نقاط البيانات
  • استخدم الإسقاط المتعامد (بشكل أساسي، تخطي المحور z)

الآن أنا عالق في العثور على عملية التدوير الصحيحة.حاولت العمل مع acos أو atan وإعداد مصفوفتي دوران.يبدو أن كلتا الطريقتين (باستخدام acos، باستخدام atan) تعطيني نتيجة خاطئة.ربما يمكنك مساعدتي هنا!

كود ماتلاب كالتالي:

b = atan(n(1) / n(2));
rotb = [cos(b) -sin(b) 0; sin(b) cos(b) 0; 0 0 1];
n2 = n * rotb;
a = atan(n(1) / n(3));
rota = [cos(a) 0 sin(a); 0 1 0; -sin(a) 0 cos(a)];
n3 = n2 * rotaows:

أتوقع n2 أن يكون مكون y يساوي الصفر.ولكن هذا فشل بالفعل بالنسبة للمتجه (-0.6367، 0.7697، 0.0467).

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

المحلول

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

  • دعنا نسمي المتجه الطبيعي لطائرتك بالمحور z الجديد.
  • يمكنك إنشاء المحور y الجديد عن طريق عبور المحور x القديم مع المحور z الجديد (العمودي في طائرتك).
  • أنشئ محور x الجديد عن طريق تقاطع z الجديد مع y الجديد.
  • حول كل متجهات المحاور الجديدة إلى متجهات وحدة (الطول 1).
  • لكل نقطة لديك، قم بإنشاء متجه من نقطة الأصل الجديدة إلى النقطة (طرح متجه للنقطة - مستوى_أصل).ما عليك سوى النقاط باستخدام متجهات الوحدات x وy الجديدة الجديدة وستحصل على زوج (x,y) يمكنك رسمه!

إذا كان لديك بالفعل وظائف منتج متقاطع ونقطة، فهذا مجرد بضعة أسطر من التعليمات البرمجية.أعلم أن الأمر يعمل لأن معظم ألعاب الفيديو ثلاثية الأبعاد التي كتبتها تعمل بهذه الطريقة.

الخدع:

  • انتبه إلى الاتجاهات التي تشير إليها ناقلاتك.إذا كانت تشير إلى الاتجاه الخاطئ، قم بإبطال المتجه الناتج أو تغيير ترتيب حاصل الضرب الاتجاهي.
  • ستواجه مشكلة إذا كان الوضع الطبيعي لطائرتك مطابقًا تمامًا لمحور x الأصلي.

نصائح أخرى

ماذا عن:

قم بتحليل المتجه العادي إلى متجه في المستوى XY ومتجه Z.ثم قم بتطبيق دوران حول المحور Z لمحاذاة المتجه XY مع أحد المحاور.ثم ابحث عن حاصل الضرب النقطي للخط العمودي بالمحور Z، وقم بالتدوير على طول أي من X وY الذي تصطف معه.

تتمثل الفكرة في ربط المتجه العادي بالحرف Z، وبذلك يصبح مستواك الآن هو المستوى XY.

وعلى الرغم من وجود ردود أخرى مثيرة للاهتمام، إلا أن هذا هو الحل الذي توصلنا إليه أثناء انتظار الإجابات:

function roti = magic_cosini(n)
    b = acos(n(2) / sqrt(n(1)*n(1) + n(2)*n(2)));
    bwinkel = b * 360 / 2 / pi;
    if (n(1) >= 0)
        rotb = [cos(-b) -sin(-b) 0; sin(-b) cos(-b) 0; 0 0 1];
    else
        rotb = [cos(-b) sin(-b) 0; -sin(-b) cos(-b) 0; 0 0 1];
    end
    n2 = n * rotb;
    a = acos(n2(3) / sqrt(n2(2)*n2(2) + n2(3)*n2(3)));
    awinkel = a * 360 / 2 / pi;
    rota = [1 0 0; 0 cos(-a) -sin(-a); 0 sin(-a) cos(-a)];
    roti = rotb * rota;

(إنها تُرجع مصفوفة دوران مزدوجة صحيحة نأمل)

كان الخلل الذي كان لدينا من قبل وتم إصلاحه هنا هو esp.التعامل مع علامة المكون X، والتي لم يتم تغطيتها في حسابات جيب التمام.وهذا ما جعلنا ندور في الاتجاه الخاطئ مرة واحدة (الدوران بزاوية 180 درجة).

آمل أن أجد الوقت أيضًا لتجربة حل نصردنا!من الجيد دائمًا تجنب علم المثلثات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top