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:
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)