diff --git a/lib/gears/matrix.lua b/lib/gears/matrix.lua index c6f7b2f7..a6bc9755 100644 --- a/lib/gears/matrix.lua +++ b/lib/gears/matrix.lua @@ -51,6 +51,17 @@ function matrix.create_rotate(angle) return matrix.create(c, s, -s, c, 0, 0) end +--- Create a new rotation matrix rotating around a custom point +-- @tparam number x The horizontal rotation point +-- @tparam number y The vertical rotation point +-- @tparam number angle The angle of the rotation in radians. +-- @return A new matrix describing the given transformation. +function matrix.create_rotate_at(x, y, angle) + return matrix.create_translate( -x, -y ) + * matrix.create_rotate ( angle ) + * matrix.create_translate( x, y ) +end + --- Translate this matrix -- @tparam number x The translation in x direction. -- @tparam number y The translation in y direction. @@ -80,9 +91,7 @@ end -- @tparam number angle The angle (in radiant: -2*math.pi to 2*math.pi) -- @return A transformation object function matrix:rotate_at(x, y, angle) - return self * matrix.create_translate( -x, -y ) - * matrix.create_rotate ( angle ) - * matrix.create_translate( x, y ) + return self * matrix.create_rotate_at(x, y, angle) end --- Invert this matrix diff --git a/spec/gears/matrix_spec.lua b/spec/gears/matrix_spec.lua index 873d2c47..4907468e 100644 --- a/spec/gears/matrix_spec.lua +++ b/spec/gears/matrix_spec.lua @@ -150,6 +150,30 @@ describe("gears.matrix", function() assert.is.equal(0, m.x0) assert.is.equal(0, m.y0) end) + + describe("rotate_at", function() + it("create", function() + local m = matrix.create_rotate_at(5, 5, math.pi) + assert.is.equal(-1, m.xx) + -- Stupid rounding issues... + assert.is_true(math.abs(round(m.xy) - m.xy) < 0.00000001) + assert.is_true(math.abs(round(m.yx) - m.yx) < 0.00000001) + assert.is.equal(-1, m.yy) + assert.is.equal(10, m.x0) + assert.is.equal(10, m.y0) + end) + + it("multiply", function() + local m = matrix.create_translate(-5, 0):rotate_at(5, 5, math.pi) + assert.is.equal(-1, m.xx) + -- Stupid rounding issues... + assert.is_true(math.abs(round(m.xy) - m.xy) < 0.00000001) + assert.is_true(math.abs(round(m.yx) - m.yx) < 0.00000001) + assert.is.equal(-1, m.yy) + assert.is.equal(15, m.x0) + assert.is.equal(10, m.y0) + end) + end) end) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80