Returning an angle

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
Telecorpse
Prole
Posts: 7
Joined: Thu Aug 27, 2015 12:58 am

Returning an angle

Post by Telecorpse »

I have that triangle:
Image
I know variables A and B and I want to calculate the alpha angle.
I came up with this sloppy algorithm. It returns 46 when A = B I think there is a more effective way but I couldn't find it :)

Code: Select all

degree = math.pi / 180
alpha = 0
for k = 1, 90 do
    if alpha == 0 then
        if math.tan(k * degree) >= A / B then
            alpha = k
        end
    end
end
love.graphics.print(alpha)
bio1712
Citizen
Posts: 72
Joined: Wed Aug 19, 2015 4:13 pm
Location: Italy

Re: Returning an angle

Post by bio1712 »

You can use this:

print(math.atan2(A,B)) --radians
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Returning an angle

Post by ivan »

One thing you could do is treat the hypotenuse and side B as vectors where:
vector 1 = [-b, 0] -- side b
vector 2 = [-b, a] -- hypotenuse + side a

Imagine the two vectors originating from the corner alpha.

Then the problem becomes finding the angle between the two vectors:

Code: Select all

--- Returns the angle in radians between two vectors
--- Description:
-- Uses the dot product (D) to find the angle (A) between two vectors (a,b)
-- normalized vectors:
-- D = dot(a,b)
-- cos(A) = D
-- A = acos(D)
-- non-normalized vectors:
-- D = dot(a,b)
-- cos(A) = D/(len(a)*len(b))
-- A = acos(D/(len(a)*len(b)))
--- Non-commutative:
-- vang(a,b) == -vang(b,a)
--- Result:
-- -pi <= A <= pi (depending on the angle between the two vectors)
-- A is zero when one of the vectors has zero length
--- Parameters:
-- @param ax, ay first vector
-- @param bx, by second vector
-- @return the angle between the two vectors
function vec.vang(ax, ay, bx, by)
  -- local a = len2(ax, ay)*len2(bx, by)
  local a = (ax*ax + ay*ay)*(bx*bx + by*by)
  a = sqrt(a)
  if a > 0 then
    -- a = acos(dot(ax, ay, bx, by)/a)
    a = acos((ax*bx + ay*by)/a)
    if ax*by - ay*bx < 0 then
      a = -a
    end
  end
  return a
end
To find the angle you would write:

Code: Select all

local a = math.vang(-b, 0, -b, a)
atan2 could be used to solve the problem too, but it's slightly less accurate and you have to be careful that neither of the sides has zero length:

Code: Select all

--- Returns the angle in radians between two vectors
--- Description:
-- Uses atan2 to find the angle (R) which is slightly less accurate then acos
-- Rd = atan2(b) - atan2(a)
-- R = (Rd + pi)%(2*pi) - pi
--- Non-commutative:
-- vang2(a,b) == -vang2(b,a)
--- Result:
-- -pi <= R < pi (depending on the angle between the vectors)
-- R could be -pi but never pi
-- R could be non-zero even when one of the vectors has zero length
--- Parameters:
-- @param ax, ay first vector
-- @param bx, by second vector
-- @return the angle between the two vectors
function vec.vang2(ax, ay, bx, by)
  local a = atan2(by, bx) - atan2(ay, ax)
  return (a + pi)%(pi2) - pi
end
Solution using atan2:

Code: Select all

local a = math.vang2(-b, 0, -b, a)

Edit: bio1712's solution is better in this case, but still you have to be careful neither side is 0.

Also note that these two functions are non-commutative, so:

Code: Select all

math.vang(x, y, x2, y2) = -math.vang(x2, y2, x, y)
Lastly, if your triangle sides are normalized, finding the angle could be further simplified:

Code: Select all

D = dot(a,b) -- ax*bx + ay*by
A = math.acos(D)
Last edited by ivan on Thu Aug 27, 2015 5:54 am, edited 2 times in total.
Telecorpse
Prole
Posts: 7
Joined: Thu Aug 27, 2015 12:58 am

Re: Returning an angle

Post by Telecorpse »

bio1712 wrote:You can use this:

print(math.atan2(A,B)) --radians
Thanks a lot!
Zarty55
Citizen
Posts: 79
Joined: Thu Jul 25, 2013 2:36 am

Re: Returning an angle

Post by Zarty55 »

Telecorpse wrote:
bio1712 wrote:You can use this:

print(math.atan2(A,B)) --radians
Thanks a lot!
Just a small reminder: the function is defined as math.atan2(Y, X). If using in a cartesian plane, the coordinates are flipped (Y first then X).
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 3 guests