Atan และ atan2 ใช้สำหรับเกมอะไร


47

ฉันกำลังมีความเข้าใจปัญหาบางอย่างMath.tan()และและMath.atan()Math.atan2()

ฉันมีความรู้พื้นฐานเกี่ยวกับตรีโกณมิติ แต่การใช้ SIN, COS และ TAN เป็นต้นสำหรับการพัฒนาเกมนั้นเป็นเรื่องใหม่สำหรับฉัน

ฉันกำลังอ่านบทช่วยสอนบางอย่างและฉันเห็นว่าโดยการใช้แทนเจนต์เราจะได้มุมที่วัตถุหนึ่งต้องหมุนด้วยการเผชิญหน้ากับวัตถุอื่นเช่นเมาส์ของฉัน เหตุใดเราจึงยังต้องใช้ atan หรือ atan2


atan ใช้เพื่อกำหนดมุมซึ่งมีประโยชน์สำหรับสิ่งต่าง ๆ นับพัน คุณมีคำถามจริงเกี่ยวกับการใช้งานหรือคุณแค่ต้องการความช่วยเหลือทางคณิตศาสตร์ทั่วไป?
BlueRaja - Danny Pflughoeft

5
คุณต้องเข้าใจคณิตศาสตร์ / เรขาคณิตที่อยู่เบื้องหลังฟังก์ชันเหล่านั้นอย่างแน่นอน เมื่อคุณเชี่ยวชาญพวกเขาพวกเขาจะกลายเป็นส่วนหนึ่งของ "ความเข้าใจโลก" ของคุณเช่นไวยากรณ์พื้นฐานที่คุณใช้พูดทุกวัน เมื่อคุณสามารถ "พูดคณิตศาสตร์ / เรขาคณิต" คุณจะเห็นว่าฟังก์ชั่นเหล่านั้นเป็นเครื่องมือที่ง่ายต่อการใช้งานเพื่อให้ได้ผลลัพธ์ที่เป็นธรรมชาติที่สุดที่จะใช้
FxIII

บทเรียนเหล่านั้นผิดหรือคุณเข้าใจผิด คุณใช้ atan2 () เพื่อให้ได้มุมจากวัตถุหนึ่งไปอีกวัตถุหนึ่ง วิธีการทำงานดังกล่าวอธิบายไว้ด้านล่าง
jhocking

ขอบคุณผู้คนสำหรับคำตอบตอนนี้ฉันรู้สึกเสียใจที่ไม่ได้ให้ความสนใจในชั้นเรียนมากขึ้น
sutoL

คำตอบ:


93

สูตรแทนเจนต์คือ:

tan(angle) = opposite/adjacent

อ้างถึงภาพวาดนี้:

ไดอะแกรมของสามเหลี่ยมมุมฉากมีมุมทีต้าและด้านตรงข้ามและด้านข้างติดกัน

ในกรณีที่aเป็นด้านที่อยู่ติดกันoเป็นฝั่งตรงข้ามและthetaเป็นมุม ในทำนองเดียวกันไซน์และโคไซน์เป็นบาป (อ่างทอง) = o / h และ cos (อ่างทอง) = a / h ซึ่งhเป็นด้านยาว: http://www.mathwords.com/s/sohcahtoa.htm

ในขณะเดียวกันatan(สั้น ๆ สำหรับอาร์กแทนเจนต์หรือที่รู้จักกันว่าอินแทนเจนต์แทนเจนต์ ) กลับด้านtanดังนี้:

atan(opposite/adjacent) = angle

ดังนั้นถ้าคุณรู้ค่าของทั้งสองตรงข้ามและด้านที่อยู่ติดกัน (ตัวอย่างเช่นโดยการลบพิกัดของวัตถุจากพิกัดเมาส์) atanคุณจะได้รับความคุ้มค่าของมุมที่มี

ในการพัฒนาเกมมันสามารถเกิดขึ้นได้ค่อนข้างบ่อยครั้งที่ด้านประชิดเท่ากับ 0 (เช่นพิกัด x ของเวกเตอร์ที่ 0) การจำไว้ว่าtan(angle) = opposite/adjacentโอกาสที่จะเกิดข้อผิดพลาดโดยแบ่งเป็นศูนย์นั้นน่าจะชัดเจน ดังนั้นไลบรารีจำนวนมากจึงเสนอฟังก์ชันที่เรียกว่าatan2ซึ่งให้คุณระบุทั้งxและyพารามิเตอร์เพื่อหลีกเลี่ยงการหารด้วยศูนย์สำหรับคุณและกำหนดมุมในจตุภาคที่ถูกต้อง

ไดอะแกรม atan2

(แผนภาพความอนุเคราะห์ของแกเร็ ธ โปรดโหวตคำตอบของเขาด้วย)


การใช้ตรีโกณมิติในการพัฒนาเกมค่อนข้างธรรมดาโดยเฉพาะกับเวกเตอร์ แต่โดยปกติแล้วไลบรารีจะซ่อนตรีโกณมิติที่เหมาะกับคุณ คุณสามารถใช้ sin / cos / tan สำหรับงานจำนวนมากที่เกี่ยวข้องกับการดัดแปลงทางเรขาคณิตเพื่อค้นหาค่าจากรูปสามเหลี่ยม สิ่งที่คุณต้องมีคือ 3 ค่า (ความยาวด้าน / ค่ามุม) เพื่อค้นหาค่าอื่น ๆ ของรูปสามเหลี่ยมสี่เหลี่ยมผืนผ้าดังนั้นมันจึงมีประโยชน์มาก

คุณยังสามารถใช้ลักษณะ "การขี่จักรยาน" ของฟังก์ชันไซน์และโคไซน์สำหรับพฤติกรรมพิเศษในเกมเช่นฉันเคยเห็น cos / sin ใช้มากในการทำให้วัตถุหมุนไปรอบ ๆ


8
มันน่าสังเกตว่า Wikipedia อธิบายถึงประเพณีอื่น ๆ สำหรับ Atan2 ( ไม่ใช่ atan) มากกว่าเพียงแค่หลีกเลี่ยงการหารด้วยศูนย์ ตัวอย่างเช่นมันแก้ไขตัวเองสำหรับ Quadrant ที่ใช้โดยปกติคุณจะต้องทำทุกอย่างด้วยตัวเอง
doppelgreener

แท้จริงแล้วบันทึกที่สำคัญมากอยู่ที่นั่น กำลังอัปเดตคำตอบของฉัน
Jesse Emond

คุณไม่ได้รับผิวสีแทนและสีขาวด้านหลังในย่อหน้าแรกที่ยาวหรือไม่? คุณต้องใช้ atan เพื่อให้ได้มุม (เช่นกลับสมการกลับด้าน) และ tan เพื่อให้ได้อัตราส่วนของด้านข้าง (นั่นคือสิ่งที่สมการบอกว่า)
jhocking

ถ้าคุณรู้ว่า o / a เท่ากับ 3 แล้วถ้าคุณต้องการมุมที่คุณทำ atan (3) นั่นคือสิ่งที่ฉันหมายถึง: ถ้าคุณต้องการแยกมุมคุณใช้ atan ตามอัตราส่วน ถ้าคุณต้องการแยกอัตราส่วนคุณใช้แทนน้ำตาลกับมุม
Jesse Emond

ฉันจะเปลี่ยนถ้อยคำของคุณเพราะมันฟังดูเหมือนคุณกำลังพูดตรงกันข้าม
jhocking

63

ป้อนคำอธิบายรูปภาพที่นี่


1
มันจะไม่สุภาพหรือไม่ที่จะแก้ไขคำตอบแรกสุดเพื่อให้มีไดอะแกรมนี้ แผนภาพนี้ยอดเยี่ยมและเหมาะอย่างยิ่งหลังจากคำอธิบายที่เป็นลายลักษณ์อักษรของ atan2 () ของ Jesse
jhocking

1
ไปข้างหน้า: เป็นแขกของฉัน! ฉันจะลบคำตอบนี้หลังจากคุณทำเสร็จแล้ว
Gareth Rees

7
ไม่ไม่. ตามทัน! เป็นที่ให้เครดิตและผู้คนยังควรโหวตที่นี่เพื่อดูแผนภาพ
Jesse Emond

12

นี่เป็นวิธีที่แตกต่างกันเล็กน้อยในการคิดเกี่ยวกับฟังก์ชั่นตรีโกณฯ - รวมทั้ง atan () และ atan2 () - ที่ฉันพบว่ามีประโยชน์ (คำอธิบายในแง่ของ "ตรงกันข้าม / ติดกัน" เพียงแค่ทำให้ฉันสับสนด้วยเหตุผลบางอย่าง)

x, y, r, theta

คุณสามารถได้จากจุดหนึ่งไปยังอีกจุดหนึ่งโดยการย้ายหน่วยx ในแนวนอนและหน่วยy ในแนวตั้ง (เรียกว่าพิกัดรูปสี่เหลี่ยมผืนผ้าหรือคาร์ทีเซียน ) หรือโดยการเคลื่อนที่เป็นระยะทางrที่มุมƟ (เรียกว่าพิกัดเชิงขั้วใน 2D)

สมมติว่าเรามีพิกัดเชิงขั้ว (r, Ɵ) และเราต้องการแปลงเป็น (x, y)

cos (Ɵ) ให้สัดส่วนrที่อยู่ตามแกนx :

  • ถ้าr = 1 ดังนั้นx = cos (Ɵ)
  • ถ้าr = 100 ดังนั้นx = 100 * cos (Ɵ)
  • โดยทั่วไปx = r * cos (Ɵ)

บาปในทำนองเดียวกัน (Ɵ) ให้สัดส่วนrที่อยู่ตามแกนy :

  • ถ้าr = 1 ดังนั้นy = sin (Ɵ)
  • ถ้าr = 100 ดังนั้นy = 100 * sin (Ɵ)
  • โดยทั่วไปy = r * sin (Ɵ)

วิธีการแปลงพิกัดสี่เหลี่ยม (x, y) เป็นพิกัดเชิงขั้ว (r, Ɵ)?

rคือด้านตรงข้ามมุมฉากของสามเหลี่ยมมุมฉากที่เกิดจากxและyดังนั้น:

  • r = sqrt (x x + y y)

สีน้ำตาล (Ɵ) ให้ความลาดชัน - เพิ่มขึ้นมากกว่าการทำงาน - ของเส้นที่มีความยาวR ดังนั้น:

  • ผิวสีแทน (Ɵ) = y / x
  • Ɵ = atan (y / x)

อย่างไรก็ตามเมื่อดำเนินการ y / x การคำนวณ 3/4 จะให้คำตอบเดียวกับการคำนวณ -3 / -4 เช่นเดียวกัน -3/4 ให้คำตอบเดียวกับ 3 / -4 ดังนั้นเราจึงมี atan2 (y, x) ที่จัดการสัญญาณแต่ละอย่างถูกต้องและป้องกันข้อผิดพลาดหารด้วยศูนย์ / อินฟินิตี้

  • Ɵ = atan2 (y, x)

4

เจสกับซิดนั้นถูกต้องแล้ว แต่ฉันสงสัยว่าคุณเข้าใจปัญหาจริงๆแล้ว

Atan2 () เป็นสิ่งจำเป็นเนื่องจาก atan () ไม่ได้บอกมุมจากแนวนอนที่คุณต้องการเพราะมันไม่ได้รับมือกับควอดเรนท์

ซึ่งหมายความว่าการใช้ atan สำหรับเวกเตอร์ (-2,2) และ (2, -2) จะให้ค่าเท่ากัน จากนั้นคุณจะเปิดสัญลักษณ์ของข้อโต้แย้งของคุณและเพิ่ม pi ลงในผลลัพธ์ นอกจากนี้คุณมีการแบ่งแยกเป็นกรณีพิเศษให้พิจารณาว่า Jesse พูดถึง นอกจากนี้ atan2 () ยังทำงานได้ดีกว่า atan เมื่อ x ใกล้กับ 0

ดังนั้นถ้าคุณต้องการมุมของเวกเตอร์ระหว่าง -pi และ pi

x = -2
y = 2
angle = Math.Atan2(y, x)

หรือ

x = -2
y = 2
angle = calculateAngle(y, x);

double CalculateAngle(double y, double x)
{
    double angle = 0;
    if (x == 0)
    {
        if (y == 0)
            angle = 0;
        else if (y > 0)
            angle = Math.PI/2;
        else
            angle = -Math.PI/2;
    }
    else
    {
        angle = Math.Atan(y/x);
        if (x < 0)
        {
            if (y > 0)
            {
                angle += Math.PI;
            }
            else if (y < 0)
            {
                angle -= Math.PI;
            }
            else
            {
                angle = Math.PI;
            }
        }
    }
    return angle;
}

1
"ซึ่งหมายความว่าการใช้ atan สำหรับเวกเตอร์ (-2,2) และ (2,2) จะให้ค่าเท่ากัน" หากเป็นกรณีนี้ atan ของคุณจะแตกอย่างไม่น่าเชื่อเพราะหนึ่งในนั้นคือ-π / 4 และอีก other / 4 อับอายกับทุกคนที่ลงคะแนนขยะนี้ขึ้นมา

รหัสยังคงผิด คุณกำลังทดสอบy==0แล้วหารด้วยxในสาขาอื่น
sam hocevar

0

ฉันจะอธิบายบางสิ่งในลักษณะที่กระชับ โปรดอ้างอิงตรีโกณมิติบทช่วยสอนออนไลน์สำหรับคำอธิบายโดยละเอียด

ให้เป็นมุม จากนั้น tan (a) = tan (a + 2 * pi)

atan คือผกผันสีแทนนั่นคือให้มุมกับผิวสีแทน เมื่อคุณโทรหา atan (tan (+2 * pi)) คำตอบจะเป็น สิ่งนี้จะไม่เพียงพอสำหรับใบสมัครของคุณ

atan2 จะทำการโต้แย้ง 2 ครั้งเพื่อช่วยในสถานการณ์นี้ atan รับ x และ y ซึ่งโดยทั่วไปจะเป็น cos (a) และ sin (a)

atan2 (sin (a), cos (a)) = a at2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin และ cos มีสัญญาณต่างกันนำไปสู่ เพื่อคำตอบอื่น * /

โปรดหาบทช่วยสอนเพื่ออธิบายว่าทำไมจึงเป็นเช่นนี้

รหัสของคุณควรเป็นดังนี้:

if (mouseMoved)
{
  double angle = atan2(mousey - objecty, mousex - objectx);

  object. setTransform to Rotate(angle);

  // If you want to print it
  print radian_to_degrees(angle); // Because angle is in radian 360 degrees = 2*Pi radians
}

tan(a) = - tan(-a)สมการที่คุณต้องการแสดงออกอาจเป็นtan(a) = tan(pi+a)
Ali1S232

0

หนึ่งใช้สำหรับ atan2ฉันพบในโค้ดของฉันคือ "ลงนามมุม"

โดยปกติวิธีที่คุณจะพบมุมระหว่างเวกเตอร์สองตัวคือ

inline float angleWith( const Vector2f& o ) const
{
    return acosf( this->normalizedCopy().dot(o.normalizedCopy()) ) ;
}

แต่นี่ไม่ได้บอกคุณว่า "โอกาสในการขาย" ตัวใดตัวหนึ่ง (นั่นคือ ข้อมูลนี้อาจมีความสำคัญสำหรับการติดตามท่าทาง

คุณสามารถหามุมได้จากแกน x (1,0)สำหรับเวกเตอร์ทั้งสองตัว แต่มีปัญหาที่น่าสงสัยเกี่ยวกับความกำกวม: เวกเตอร์ที่มีมุม 315 องศาจะส่งกลับ 45 องศาโดยใช้cosวิธีการด้านบนและทำมุม 45 องศา คุณสามารถทำการตรวจสอบสัญญาณในการแก้ไขปัญหานั้นหรือคุณสามารถใช้yatan2

// Returns + if this leads o.
// more expensive than unsigned angle.
inline float signedAngleWith( const Vector2f& o ) const
{
  float aThis = atan2f( y, x );
  float aO = atan2f( o.y, o.x ) ;
  return aThis - aO ;
}

0

โปรดทราบว่า atan ไม่เสียหาย arctan หรือ tan inverse เป็นเพียงฟังก์ชันระหว่าง -PI / 2 กับ PI / 2 มันทำซ้ำรูปแบบนี้ แต่แล้วมันก็ไม่ใช่ฟังก์ชั่นที่เป็นปัญหาสำหรับคอมพิวเตอร์เนื่องจากมันไม่สามารถตอบได้หลายคำตอบ

สิ่งนี้จะเหมือนกันสำหรับ asin ระหว่าง -PI / 2 ถึง PI / 2 และ acos ระหว่าง 0 ถึง PI นี่เป็นช่วงที่ง่ายที่สุดสำหรับฟังก์ชันที่จะเกิดขึ้น สำหรับอาตานและอาซินมันเริ่มจากลบมากที่สุดไปจนถึงเป็นบวกที่สุด สำหรับ acos มันไปจากบวกที่สุดไปมากที่สุดลบ (สิ่งนี้ช่วยในการแก้ไขคำตอบที่แม่นยำยิ่งขึ้น)

ดังนั้น, acos และ atan จึงเป็นฟังก์ชันทางคณิตศาสตร์

อย่างไรก็ตาม atan2 มีประโยชน์มากกว่าสำหรับการเขียนโปรแกรมเนื่องจากมีการปฏิวัติที่สมบูรณ์ (PI เป็นเรเดียนหรือ 360 องศาหรือ 400 องศา) โปรดทราบว่าพวกเขาผลิตเพียงหนึ่งสำหรับผิวสีแทนไม่ได้เพื่อบาปหรือเพราะ ตาลเป็นคนเดียวที่ใช้แนวนอนและแนวตั้ง (x, y)

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