Merge pull request #59 from idbrii/fix-angleto

Fix angle_to to produce signed angle instead of incorrect results
This commit is contained in:
mcclure 2021-06-17 11:25:16 -04:00 committed by GitHub
commit 85988fc7c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 7 deletions

View File

@ -228,22 +228,31 @@ function vec2.perpendicular(a)
return new(-a.y, a.x)
end
--- Angle from one vector to another.
--- Signed angle from one vector to another.
-- Rotations from +x to +y are positive.
-- @tparam vec2 a Vector
-- @tparam vec2 b Vector
-- @treturn number angle
-- @treturn number angle in (-pi, pi]
function vec2.angle_to(a, b)
if b then
return atan2(a.y - b.y, a.x - b.x)
local angle = atan2(b.y, b.x) - atan2(a.y, a.x)
-- convert to (-pi, pi]
if angle > math.pi then
angle = angle - 2 * math.pi
elseif angle <= -math.pi then
angle = angle + 2 * math.pi
end
return angle
end
return atan2(a.y, a.x)
end
--- Angle between two vectors.
--- Unsigned angle between two vectors.
-- Directionless and thus commutative.
-- @tparam vec2 a Vector
-- @tparam vec2 b Vector
-- @treturn number angle
-- @treturn number angle in [0, pi]
function vec2.angle_between(a, b)
if b then
if vec2.is_vec2(a) then

View File

@ -45,6 +45,4 @@ project_from(out, a, b)
mirror_on(out, a, b)
reflect(out, i, n)
refract(out, i, n, ior)
angle_to(a, b)
angle_between(a, b)
--]]

View File

@ -203,6 +203,62 @@ describe("vec2:", function()
assert.is.equal(temp, vec2(-1, -2))
end)
it("finds angle from one 2-vector to another", function()
local d = {
right = vec2(1, 0),
down = vec2(0, -1),
left = vec2(-1, 0),
up = vec2(0, 1),
}
assert.is.equal(math.deg(d.right:angle_to(d.right)), 0.0)
assert.is.equal(math.deg(d.right:angle_to(d.down)), -90.0)
assert.is.equal(math.deg(d.right:angle_to(d.left)), 180.0)
assert.is.equal(math.deg(d.right:angle_to(d.up)), 90.0)
assert.is.equal(math.deg(d.down:angle_to(d.right)), 90.0)
assert.is.equal(math.deg(d.down:angle_to(d.down)), 0.0)
assert.is.equal(math.deg(d.down:angle_to(d.left)), -90.0)
assert.is.equal(math.deg(d.down:angle_to(d.up)), 180.0)
assert.is.equal(math.deg(d.left:angle_to(d.right)), 180.0)
assert.is.equal(math.deg(d.left:angle_to(d.down)), 90.0)
assert.is.equal(math.deg(d.left:angle_to(d.left)), 0.0)
assert.is.equal(math.deg(d.left:angle_to(d.up)), -90.0)
assert.is.equal(math.deg(d.up:angle_to(d.right)), -90.0)
assert.is.equal(math.deg(d.up:angle_to(d.down)), 180.0)
assert.is.equal(math.deg(d.up:angle_to(d.left)), 90.0)
assert.is.equal(math.deg(d.up:angle_to(d.up)), 0.0)
end)
it("finds angle between two 2-vectors", function()
local d = {
right = vec2(1, 0),
down = vec2(0, -1),
left = vec2(-1, 0),
up = vec2(0, 1),
}
assert.is.equal(math.deg(d.right:angle_between(d.right)), 0.0)
assert.is.equal(math.deg(d.right:angle_between(d.down)), 90.0)
assert.is.equal(math.deg(d.right:angle_between(d.left)), 180.0)
assert.is.equal(math.deg(d.right:angle_between(d.up)), 90.0)
assert.is.equal(math.deg(d.down:angle_between(d.right)), 90.0)
assert.is.equal(math.deg(d.down:angle_between(d.down)), 0.0)
assert.is.equal(math.deg(d.down:angle_between(d.left)), 90.0)
assert.is.equal(math.deg(d.down:angle_between(d.up)), 180.0)
assert.is.equal(math.deg(d.left:angle_between(d.right)), 180.0)
assert.is.equal(math.deg(d.left:angle_between(d.down)), 90.0)
assert.is.equal(math.deg(d.left:angle_between(d.left)), 0.0)
assert.is.equal(math.deg(d.left:angle_between(d.up)), 90.0)
assert.is.equal(math.deg(d.up:angle_between(d.right)), 90.0)
assert.is.equal(math.deg(d.up:angle_between(d.down)), 180.0)
assert.is.equal(math.deg(d.up:angle_between(d.left)), 90.0)
assert.is.equal(math.deg(d.up:angle_between(d.up)), 0.0)
end)
-- Do this last, to insulate tests from accidental state contamination
-- Do vec3 tests last, to insulate tests from accidental state contamination
it("converts a 2-vector to a 3-vector", function()