ฉันจะใช้ผลิตภัณฑ์ดอทเพื่อรับมุมระหว่างเวกเตอร์สองตัวได้อย่างไร


16

ฉันกำลังเรียนรู้ที่จะใช้เวกเตอร์ปกติในเกมของฉัน

ฉันเรียนรู้ว่าเพื่อทราบมุมระหว่างเวกเตอร์สองตัวฉันสามารถใช้ผลิตภัณฑ์ดอท สิ่งนี้ทำให้ฉันมีค่าระหว่าง -1 และ 1 ที่

  • 1 หมายถึงเวกเตอร์นั้นขนานกันและหันไปในทิศทางเดียวกัน (มุมคือ 180 องศา)
  • -1 หมายถึงพวกมันขนานและหันหน้าไปทางทิศทางตรงกันข้าม (ยังคง 180 องศา)
  • 0 หมายถึงมุมระหว่างพวกเขาคือ 90 องศา

ฉันอยากรู้วิธีแปลงผลคูณดอทของเวกเตอร์สองตัวเป็นมุมจริงเป็นองศา ตัวอย่างเช่นหากผลิตภัณฑ์ดอทของเวกเตอร์สองตัวคือ0.28อะไรมุมที่สอดคล้องกันคือระหว่าง 0 ถึง 360 องศา


1
โปรดทราบว่าการใช้ผลิตภัณฑ์ dot ของคุณตั้งใจจะทำงานเฉพาะเมื่อเวกเตอร์เริ่มต้นเป็นเวกเตอร์หน่วย
sam hocevar

@ SamHocevar ใช่นั่นคือสิ่งที่ฉันหมายถึง
user3150201


1
@ user3150201 คำตอบของ Alex ถูกต้อง แต่คุณควรพิจารณาด้วยว่าคุณต้องได้มุมที่แท้จริงเป็นองศาหรือไม่ กรณีเดียวที่ฉันสามารถคิดออกว่านี่เป็นสิ่งจำเป็นจริง ๆ หรือไม่คือการแสดงบางสิ่งบางอย่างในระดับองศาบน UI มิฉะนั้นอาจมีแอปพลิเคชั่นไม่กี่ตัวที่คุณไม่สามารถทำงานโดยตรงกับไซน์และโคไซน์ได้
TravisG

คำตอบ:


22

dot(A,B) = |A| * |B| * cos(angle)
ซึ่งสามารถจัดใหม่
angle = arccos(dot(A,B) / (|A|* |B|))ได้

ด้วยสูตรนี้คุณสามารถหามุมที่เล็กที่สุดระหว่างสองเวกเตอร์ซึ่งจะอยู่ระหว่าง 0 ถึง 180 องศา หากคุณต้องการระหว่าง 0 ถึง 360 องศาคำถามนี้อาจช่วยคุณได้


มุมระหว่างเวกเตอร์ขนานสองตัวที่ชี้ไปในทิศทางเดียวกันควรเป็น 0 องศาไม่ใช่ 180


+1 สำหรับ "โดยวิธีมุมระหว่างเวกเตอร์สองขนานที่ชี้ไปในทิศทางเดียวกันควรเป็น 0 องศาไม่ใช่ 180"
ธารา

8

ฉันจะขยายความคิดเห็นของ TravisG เล็กน้อยและให้คำตอบอีกครั้งใช้ประโยชน์จากข้อเท็จจริงที่ว่าคำถามของคุณมีแท็ก "2D"

คุณสามารถหามุมระหว่างเวกเตอร์สองตัวโดยใช้ผลิตภัณฑ์ดอท แต่คุณไม่สามารถหามุมที่เซ็นชื่อระหว่างสองเวกเตอร์ที่ใช้มันได้ อีกวิธีหนึ่งถ้าคุณต้องการเปลี่ยนตัวละครเมื่อเวลาผ่านไปหนึ่งจุดผลิตภัณฑ์จุดจะทำให้คุณหันไปมาก แต่ไม่ใช่ทิศทาง อย่างไรก็ตามมีสูตรง่าย ๆ อีกสูตรหนึ่งซึ่งมีประโยชน์มากเมื่อรวมกับผลิตภัณฑ์ดอท คุณไม่เพียง แต่มี

dot(A,B) = |A| * |B| * cos(angle)

นอกจากนี้คุณยังสามารถใช้สูตรอื่น (ชื่อฉันทำขึ้นเพื่อความถูกต้องทางการเมือง):

pseudoCross(A,B) = |A| * |B| * sin(angle)

โดยที่ถ้า A = (a, b), B = (x, y) ดังนั้น pseudoCross (A, B) จะถูกกำหนดให้เป็นองค์ประกอบที่สามของผลิตภัณฑ์ข้าม (a, b, 0) x (x, y, 0 ) ในคำอื่น ๆ :

a*x+b*y = |A| * |B| * cos(angle)

-b*x+a*y = |A| * |B| * sin(angle)

มุมที่เซ็นชื่อเต็มคือangle=atanfull(-b*x+a*y,a*x+b*y)(ฟังก์ชัน atanfull หรือ atan2 ยกโทษให้คุณถ้าคุณผ่านค่าที่ไม่ได้ทำให้เป็นมาตรฐาน) หาก A และ B ถูกทำให้เป็นมาตรฐานนั่นคือถ้า|A|=|B|=1สิ่งเหล่านี้เป็นเพียง:

a*x+b*y = cos(angle)

-b*x+a*y = sin(angle)


สำหรับคำอธิบายที่ลึกกว่าโปรดทราบว่าสมการข้างต้นสามารถแสดงได้โดยสมการเมทริกซ์:

[ a,b]   [x]   [cos(angle)]
[-b,a] * [y] = [sin(angle)]

แต่ A และ B สามารถแสดงเป็นa=cos(ang1), b=sin(ang1)สำหรับค่าบางอย่างang1(ไม่angle) ดังนั้นเมทริกซ์ทางซ้ายคือเมทริกซ์การหมุนที่หมุนเวกเตอร์ (x, y) ด้วยจำนวน -ang1 นี่เทียบเท่ากับการเปลี่ยนเป็นกรอบอ้างอิงโดยที่เวกเตอร์หน่วย "A" ถือเป็นเวกเตอร์ / แกน (1,0)! ดังนั้นเพียงแค่วาดวงกลมหน่วย / สามเหลี่ยมมุมฉากในกรอบนี้คุณจะเห็นได้ว่าทำไมเวกเตอร์ที่ได้ของผลิตภัณฑ์นั้นคืออะไร (cos (มุม), sin (มุม))

ถ้าคุณเขียน (a, b) และ (x, y) ในรูปแบบขั้วและใช้สูตรผลต่างมุม cos(l)*cos(m)+sin(l)*sin(m)=cos(l-m)และsin(l)*cos(m)-cos(l)*sin(m)=sin(l-m)คุณแสดงว่าไซน์ / โคไซน์ได้รับจากผลิตภัณฑ์นี้เนื่องจาก (lm) = angle อีกวิธีหนึ่งอัตลักษณ์เหล่านั้นสามารถนำมาใช้เพื่อดูว่าทำไมผลิตภัณฑ์เชิงเส้นที่ระบุด้านบนหมุนเวกเตอร์

อัตลักษณ์เหล่านี้ทั้งหมดหมายความว่าคุณไม่ค่อยต้องการมุม เนื่องจากมุมอาจเป็นสิ่งแปลก ๆ - เรเดียน / องศาอนุสัญญาสำหรับอินเวอร์สไซน์ / โคไซน์ความจริงที่ว่าพวกเขาทำซ้ำทุก ๆ 2 * pi - นี่จะมีประโยชน์มากขึ้นและช่วยให้คุณประหยัดได้มากถ้า "ตรรกะ (<180)"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.