Source: core/drawing/viewbox/viewboxFastAffineTransform.js

/**
 * @fileoverview A class providing optimizations and extensions for
 * class goog.math.AffineTransform, e.g., to avoid object allocations.
 * @private
 */

goog.provide('xrx.viewbox.FastAffineTransform');



goog.require('goog.math');
goog.require('goog.math.AffineTransform');



/**
 * A class providing optimizations and extensions for class
 * goog.math.AffineTransform.
 * @constructor
 * @private
 */
xrx.viewbox.FastAffineTransform = function() {

  goog.base(this);
 
  this.identity_;

  this.inverse_;

  this.clone_;
};
goog.inherits(xrx.viewbox.FastAffineTransform, goog.math.AffineTransform);



/**
 * Returns an identity matrix object without allocating a new object.
 * @return {xrx.viewbox.FastAffineTransform} The identity matrix.
 */
xrx.viewbox.FastAffineTransform.prototype.getIdentity = function() {
  if (!this.identity_) this.identity_ = new xrx.viewbox.FastAffineTransform();
  this.identity_.setTransform(1, 0, 0, 1, 0, 0);
  return this.identity_;
};



/**
 * Returns an inverse matrix object without allocating a new object.
 * @return {xrx.viewbox.FastAffineTransform} The inverse matrix.
 */
xrx.viewbox.FastAffineTransform.prototype.getInverse = function() {
  if (!this.inverse_) this.inverse_ = new xrx.viewbox.FastAffineTransform();
  var det = this.getDeterminant();
  this.inverse_.setTransform(
    this.m11_ / det,
    -this.m10_ / det,
    -this.m01_ / det,
    this.m00_ / det,
    (this.m01_ * this.m12_ - this.m11_ * this.m02_) / det,
    (this.m10_ * this.m02_ - this.m00_ * this.m12_) / det
  );
  return this.inverse_;
};



/**
 * Returns a temporary clone of this affine transform without allocating
 * a new object.
 * @return {xrx.viewbox.FastAffineTransform} The clone.
 */
xrx.viewbox.FastAffineTransform.prototype.getClone = function() {
  if (!this.clone_) this.clone_ = new xrx.viewbox.FastAffineTransform();
  return this.clone_.copyFrom(this);
};


/**
 * Transforms a coordinate point according to this transformation matrix.
 * @param {Array<number>} The coordinate point [x, y] to be transformed.
 * @param {Array<number>} The target point to store the result of the
 *   transformation.
 * @return {Array<number>} A coordinate point.
 */
xrx.viewbox.FastAffineTransform.prototype.transformPoint = function(point, opt_targetPoint) {
  var p = opt_targetPoint !== undefined ? opt_targetPoint : new Array(2);
  this.createInverse().transform(point, 0, p, 0, 1);
  return p;
};



/**
 * Returns the current scale of this transformation matrix.
 * @return {number} The scale.
 */
xrx.viewbox.FastAffineTransform.prototype.getScale = function() {
  var rotation = this.getRotation();
  this.getClone().rotate(goog.math.toRadians(360 - rotation));
  return this.clone_.getScaleX();
};



/**
 * Returns the current rotation of this transformation matrix in
 * a normalized form (either 0, 90, 180, or 270).
 * @return {number} The rotation in degrees.
 */
xrx.viewbox.FastAffineTransform.prototype.getRotation = function() {
  var atan = Math.round(Math.atan2(this.getShearY(), this.getScaleY()));
  var toDegree = {
    '0': 0,
    '2': 90,
    '3': 180,
    '-2': 270
  }
  return toDegree[atan]; 
};



xrx.viewbox.FastAffineTransform.prototype.disposeInternal = function() {
  this.identity_ = null;
  this.inverse_ = null;
  this.clone_ = null;
};