Jelajahi Sumber

WARNING: REDESIGN: `Vector2Angle()`<-->`Vector2LineAngle()` #2887

Ray 2 tahun lalu
induk
melakukan
5361d498c3
3 mengubah file dengan 120 tambahan dan 13 penghapusan
  1. 106 0
      examples/others/raymath_vector_angle.c
  2. TEMPAT SAMPAH
      examples/others/raymath_vector_angle.png
  3. 14 13
      src/raymath.h

+ 106 - 0
examples/others/raymath_vector_angle.c

@@ -0,0 +1,106 @@
+/*******************************************************************************************
+*
+*   raylib [shapes] example - Vector Angle
+*
+*   Example originally created with raylib 1.0, last time updated with raylib 4.2
+*
+*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+*   BSD-like license that allows static linking with closed source software
+*
+*   Copyright (c) 2023 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include "raymath.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [math] example - vector angle");
+
+    Vector2 v0 = { screenWidth/2, screenHeight/2 };
+    Vector2 v1 = { 100.0f, 80.0f };
+    Vector2 v2 = { 0 };             // Updated with mouse position
+    
+    float angle = 0.0f;             // Angle in degrees
+    int angleMode = 0;              // 0-Vector2Angle(), 1-Vector2LineAngle()
+
+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        if (IsKeyPressed(KEY_SPACE)) angleMode = !angleMode;
+        
+        if (angleMode == 0)
+        {
+            // Calculate angle between two vectors, considering a common origin (v0)
+            v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f });
+            v2 = GetMousePosition();
+            angle = Vector2Angle(Vector2Normalize(Vector2Subtract(v1, v0)), Vector2Normalize(Vector2Subtract(v2, v0)))*RAD2DEG;
+        }
+        else if (angleMode == 1)
+        {
+            // Calculate angle defined by a two vectors line, in reference to horizontal line
+            v1 = (Vector2){ screenWidth/2, screenHeight/2 };
+            v2 = GetMousePosition();
+            angle = Vector2LineAngle(v1, v2)*RAD2DEG;
+        }
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+            
+            if (angleMode == 0) DrawText("v0", v0.x, v0.y, 10, DARKGRAY);
+            DrawText("v1", v1.x, v1.y, 10, DARKGRAY);
+            DrawText("v2", v2.x, v2.y, 10, DARKGRAY);
+
+            if (angleMode == 0)
+            {
+                DrawText("MODE: Angle between V1 and V2", 10, 10, 20, BLACK);
+                
+                DrawLineEx(v0, v1, 2.0f, BLACK);
+                DrawLineEx(v0, v2, 2.0f, RED);
+                
+                // TODO: Properly draw circle sector
+                DrawCircleSector(v0, 40.0f, Vector2LineAngle(v0, v1)*RAD2DEG, angle, 32, Fade(GREEN, 0.6f));
+            }
+            else if (angleMode == 1)
+            {
+                DrawText("MODE: Angle formed by line V1 to V2", 10, 10, 20, BLACK);
+                
+                DrawLine(0, screenHeight/2, screenWidth, screenHeight/2, LIGHTGRAY);
+                DrawLineEx(v1, v2, 2.0f, RED);
+                
+                DrawCircleSector(v1, 40.0f, 90.0f, 180 - angle - 90, 32, Fade(GREEN, 0.6f));
+            }
+            
+            DrawText("Press SPACE to change MODE", 460, 10, 20, DARKGRAY);
+            DrawText(TextFormat("ANGLE: %2.2f", angle), 10, 40, 20, LIME);
+            
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

TEMPAT SAMPAH
examples/others/raymath_vector_angle.png


+ 14 - 13
src/raymath.h

@@ -314,8 +314,19 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
 // NOTE: Angle is calculated from origin point (0, 0)
 RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
 {
-    float result = atan2f(v2.y - v1.y, v2.x - v1.x);
+    float result = 0.0f;
+    
+    float dot = v1.x*v2.x + v1.y*v2.y;      // Dot product
+    float dotClamp = (dot < -1.0f)? -1.0f : dot;    // Clamp
+    if (dotClamp > 1.0f) dotClamp = 1.0f;
 
+    result = acosf(dotClamp);
+
+    // Alternative implementation, more costly
+    //float v1Length = sqrtf((v1.x*v1.x) + (v1.y*v1.y));
+    //float v2Length = sqrtf((v2.x*v2.x) + (v2.y*v2.y));
+    //float result = -acosf((v1.x*v2.x + v1.y*v2.y)/(v1Length*v2Length));
+    
     return result;
 }
 
@@ -325,18 +336,8 @@ RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
 RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)
 {
     float result = 0.0f;
-
-    float dot = start.x*end.x + start.y*end.y;      // Dot product
-
-    float dotClamp = (dot < -1.0f)? -1.0f : dot;    // Clamp
-    if (dotClamp > 1.0f) dotClamp = 1.0f;
-
-    result = acosf(dotClamp);
-
-    // Alternative implementation, more costly
-    //float v1Length = sqrtf((start.x*start.x) + (start.y*start.y));
-    //float v2Length = sqrtf((end.x*end.x) + (end.y*end.y));
-    //float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length));
+    
+    result = atan2f(end.y - start.y, end.x - start.x);
 
     return result;
 }