Created
August 24, 2013 11:21
-
-
Save jarek-foksa/6327570 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # @copyright | |
| # © 2012-2013 Jarosław Foksa | |
| {createSVGMatrix} = imports 'utils/dom' | |
| {createSVGTransform} = imports 'utils/transform' | |
| {sin, cos, tan, sqrt, atan2, radToDeg, degToRad, abs, pow, signum} = imports 'utils/math' | |
| # https://github.com/WebKit/webkit/blob/master/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp | |
| # https://dvcs.w3.org/hg/FXTF/raw-file/tip/matrix/index.html | |
| exports matrix = | |
| # | a c e | | |
| # | b d f | | |
| # | 0 0 1 | | |
| a: 1 | |
| b: 0 | |
| c: 0 | |
| d: 1 | |
| e: 0 | |
| f: 0 | |
| init: (@a = 1, @b = 0, @c = 0, @d = 1, @e = 0, @f = 0) -> | |
| return @ | |
| initWithSVGMatrix: (svgMatrix) -> | |
| @a = svgMatrix.a | |
| @b = svgMatrix.b | |
| @c = svgMatrix.c | |
| @d = svgMatrix.d | |
| @e = svgMatrix.e | |
| @f = svgMatrix.f | |
| return @ | |
| initWithSVGTransform: (svgTransform) -> | |
| @initWithSVGMatrix svgTransform.matrix | |
| return @ | |
| copy: -> | |
| copy = matrix.clone().init @a, @b, @c, @d, @e, @f | |
| return copy | |
| # | 1 0 0 | | |
| # | 0 1 0 | | |
| # | 0 0 1 | | |
| reset: -> | |
| @a = 1 | |
| @b = 0 | |
| @c = 0 | |
| @d = 1 | |
| @e = 0 | |
| @f = 0 | |
| # | a c e | | A C E | | a*A+c*B a*C+c*D a*E+c*F | | |
| # | b d f | * | B D F | = | b*A+d*B b*C+d*D b*E+d*F | | |
| # | 0 0 1 | | 0 0 1 | | 0 0 1 | | |
| multiply: (matrix) -> | |
| a = (@a * matrix.a) + (@c * matrix.b) | |
| b = (@b * matrix.a) + (@d * matrix.b) | |
| c = (@a * matrix.c) + (@c * matrix.d) | |
| d = (@b * matrix.c) + (@d * matrix.d) | |
| e = (@a * matrix.e) + (@c * matrix.f) + @e | |
| f = (@b * matrix.e) + (@d * matrix.f) + @f | |
| @a = a | |
| @b = b | |
| @c = c | |
| @d = d | |
| @e = e | |
| @f = f | |
| return @ | |
| inverse: -> | |
| if @isInvertible == false | |
| return @ | |
| det = @getDeterminant() | |
| a = @d / det | |
| b = -@b / det | |
| c = -@c / det | |
| d = @a / det | |
| e = (@c * @f - @d * @e) / det | |
| f = (@b * @e - @a * @f) / det | |
| @a = a | |
| @b = b | |
| @c = c | |
| @d = d | |
| @e = e | |
| @f = f | |
| return @ | |
| translate: (x, y) -> | |
| @e += x | |
| @f += y | |
| return @ | |
| translateScaled: (x, y) -> | |
| @e = @e + (x * @a) + (y * @c) | |
| @f = @f + (x * @b) + (y * @d) | |
| return @ | |
| scale: (x, y) -> | |
| if y == undefined | |
| y = x | |
| @a = @a * x | |
| @b = @b * x | |
| @c = @c * y | |
| @d = @d * y | |
| return @ | |
| flipX: -> | |
| @scale -1, 1 | |
| return @ | |
| flipY: -> | |
| @scale 1, -1 | |
| return @ | |
| rotate: (angle, rotX = 0, rotY = 0) -> | |
| angleRad = degToRad angle | |
| cosAngle = cos angleRad | |
| sinAngle = sin angleRad | |
| rotTM = matrix.clone().init cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0 | |
| @translateScaled rotX, rotY | |
| @multiply rotTM | |
| @translateScaled -rotX, -rotY | |
| return @ | |
| skew: (xAngle, yAngle, rotX = 0, rotY = 0) -> | |
| xRad = degToRad xAngle | |
| yRad = degToRad yAngle | |
| skewTM = matrix.clone().init().shear tan(xRad), tan(yRad) | |
| @translateScaled rotX, rotY | |
| @multiply skewTM | |
| @translateScaled -rotX, -rotY | |
| return @ | |
| shear: (x, y) -> | |
| a = @a | |
| b = @b | |
| @a += y * @c | |
| @b += y * @d | |
| @c += x * a | |
| @d += x * b | |
| return @ | |
| isIdentityMatrix: -> | |
| if @a == 1 && @b == 0 && @c == 0 && @d == 1 && @e == 0 && @f == 0 | |
| return true | |
| else | |
| return false | |
| isInvertible: -> | |
| det = @getDeterminant() | |
| if det == 0 | |
| return false | |
| else | |
| return true | |
| # Returns such baseTM and scaleTM matrixes that: baseTM * scaleTM = @ | |
| # | |
| # | ±1 baseC baseE | | sx 0 0 | | @a @c @e | | |
| # | baseB ±1 baseF | * | 0 sy 0 | = | @b @d @f | | |
| # | 0 0 1 | | 0 0 1 | | 0 0 1 | | |
| extractScaleTM: -> | |
| {a, b, c, d, e, f} = @ | |
| if a == 0 | |
| a = 0.0001 | |
| if d == 0 | |
| d = 0.0001 | |
| baseTM = matrix.clone().init signum(a), b/abs(a), c/abs(d), signum(d), e, f | |
| scaleTM = matrix.clone().init abs(a), 0, 0, abs(d), 0, 0 | |
| return {baseTM, scaleTM} | |
| # Returns such baseTM and translateTM matrixes that: baseTM * translateTM = @ | |
| # | |
| # | baseA baseC 0 | | 1 0 tx | | @a @c @e | | |
| # | baseB baseD 0 | * | 0 1 ty | = | @b @d @f | | |
| # | 0 0 1 | | 0 0 1 | | 0 0 1 | | |
| extractTranslateTM: -> | |
| baseTM = matrix.clone().init @a, @b, @c, @d, 0, 0 | |
| ty = (@f*baseTM.a - @e*baseTM.b) / (-baseTM.c*baseTM.b + baseTM.d*baseTM.a) | |
| tx = (@e - baseTM.c*ty) / baseTM.a | |
| translateTM = matrix.clone().init 1, 0, 0, 1, tx, ty | |
| return {baseTM, translateTM} | |
| # Returns such baseTM and transcaleTM matrixes that: baseTM * transcaleTM = @ | |
| # | |
| # | baseA baseC 0 | | sx 0 tx | | @a @c @e | | |
| # | baseB baseD 0 | * | 0 sy ty | = | @b @d @f | | |
| # | 0 0 1 | | 0 0 1 | | 0 0 1 | | |
| extractTranscaleTM: -> | |
| {baseTM, scaleTM} = @extractScaleTM() | |
| {baseTM, translateTM} = baseTM.extractTranslateTM() | |
| # baseTM * translateTM * scaleTM = @ | |
| transcaleTM = translateTM.multiply scaleTM | |
| return {baseTM, transcaleTM} | |
| getDeterminant: -> | |
| det = (@a * @d) - (@b * @c) | |
| return det | |
| getRotation: -> | |
| rot = atan2 @b, @a | |
| rot = radToDeg rot | |
| return rot | |
| getScaleX: -> | |
| scaleX = sqrt(pow(@a,2) + pow(@b,2)) | |
| return scaleX | |
| getScaleY: -> | |
| scaleY = sqrt(pow(@c,2) + pow(@d,2)) | |
| return scaleY | |
| toSVGMatrix: -> | |
| svgMatrix = createSVGMatrix @a, @b, @c, @d, @e, @f | |
| return svgMatrix | |
| toSVGTransform: -> | |
| svgMatrix = @toSVGMatrix() | |
| svgTransform = createSVGTransform svgMatrix | |
| return svgTransform | |
| toString: -> | |
| return "matrix(#{@a}, #{@b}, #{@c}, #{@d}, #{@e}, #{@f})" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment