123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- if (!dojo._hasResource["dojox.gfx.matrix"]) { // _hasResource checks added by
- // build. Do not use
- // _hasResource directly in your
- // code.
- dojo._hasResource["dojox.gfx.matrix"] = true;
- dojo.provide("dojox.gfx.matrix");
- (function() {
- var m = dojox.gfx.matrix;
- // candidates for dojox.math:
- m._degToRad = function(degree) {
- return Math.PI * degree / 180;
- };
- m._radToDeg = function(radian) {
- return radian / Math.PI * 180;
- };
- m.Matrix2D = function(arg) {
- // summary: a 2D matrix object
- // description: Normalizes a 2D matrix-like object. If arrays is
- // passed,
- // all objects of the array are normalized and multiplied
- // sequentially.
- // arg: Object
- // a 2D matrix-like object, a number, or an array of such objects
- if (arg) {
- if (typeof arg == "number") {
- this.xx = this.yy = arg;
- } else if (arg instanceof Array) {
- if (arg.length > 0) {
- var matrix = m.normalize(arg[0]);
- // combine matrices
- for (var i = 1; i < arg.length; ++i) {
- var l = matrix, r = dojox.gfx.matrix
- .normalize(arg[i]);
- matrix = new m.Matrix2D();
- matrix.xx = l.xx * r.xx + l.xy * r.yx;
- matrix.xy = l.xx * r.xy + l.xy * r.yy;
- matrix.yx = l.yx * r.xx + l.yy * r.yx;
- matrix.yy = l.yx * r.xy + l.yy * r.yy;
- matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
- matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
- }
- dojo.mixin(this, matrix);
- }
- } else {
- dojo.mixin(this, arg);
- }
- }
- };
- // the default (identity) matrix, which is used to fill in missing
- // values
- dojo.extend(m.Matrix2D, {
- xx : 1,
- xy : 0,
- yx : 0,
- yy : 1,
- dx : 0,
- dy : 0
- });
- dojo.mixin(m, {
- // summary: class constants, and methods of dojox.gfx.matrix
- // matrix constants
- // identity: dojox.gfx.matrix.Matrix2D
- // an identity matrix constant: identity * (x, y) == (x, y)
- identity : new m.Matrix2D(),
- // flipX: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at x = 0 line: flipX * (x, y) ==
- // (-x, y)
- flipX : new m.Matrix2D({
- xx : -1
- }),
- // flipY: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at y = 0 line: flipY * (x, y) ==
- // (x, -y)
- flipY : new m.Matrix2D({
- yy : -1
- }),
- // flipXY: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at the origin of coordinates:
- // flipXY * (x, y) == (-x, -y)
- flipXY : new m.Matrix2D({
- xx : -1,
- yy : -1
- }),
- // matrix creators
- translate : function(a, b) {
- // summary: forms a translation matrix
- // description: The resulting matrix is used to translate (move)
- // points by specified offsets.
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- if (arguments.length > 1) {
- return new m.Matrix2D({
- dx : a,
- dy : b
- }); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: dojox.gfx.Point: a point-like object, which specifies
- // offsets for both dimensions
- // b: null
- return new m.Matrix2D({
- dx : a.x,
- dy : a.y
- }); // dojox.gfx.matrix.Matrix2D
- },
- scale : function(a, b) {
- // summary: forms a scaling matrix
- // description: The resulting matrix is used to scale (magnify)
- // points by specified offsets.
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- if (arguments.length > 1) {
- return new m.Matrix2D({
- xx : a,
- yy : b
- }); // dojox.gfx.matrix.Matrix2D
- }
- if (typeof a == "number") {
- // branch
- // a: Number: a uniform scaling factor used for the both
- // coordinates
- // b: null
- return new m.Matrix2D({
- xx : a,
- yy : a
- }); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: dojox.gfx.Point: a point-like object, which specifies
- // scale factors for both dimensions
- // b: null
- return new m.Matrix2D({
- xx : a.x,
- yy : a.y
- }); // dojox.gfx.matrix.Matrix2D
- },
- rotate : function(angle) {
- // summary: forms a rotating matrix
- // description: The resulting matrix is used to rotate points
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an angle of rotation in radians (>0 for CW)
- var c = Math.cos(angle);
- var s = Math.sin(angle);
- return new m.Matrix2D({
- xx : c,
- xy : -s,
- yx : s,
- yy : c
- }); // dojox.gfx.matrix.Matrix2D
- },
- rotateg : function(degree) {
- // summary: forms a rotating matrix
- // description: The resulting matrix is used to rotate points
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.rotate() for comparison.
- // degree: Number: an angle of rotation in degrees (>0 for CW)
- return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- skewX : function(angle) {
- // summary: forms an x skewing matrix
- // description: The resulting matrix is used to skew points in
- // the x dimension
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an skewing angle in radians
- return new m.Matrix2D({
- xy : -Math.tan(angle)
- }); // dojox.gfx.matrix.Matrix2D
- },
- skewXg : function(degree) {
- // summary: forms an x skewing matrix
- // description: The resulting matrix is used to skew points in
- // the x dimension
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.skewX() for comparison.
- // degree: Number: an skewing angle in degrees
- return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- skewY : function(angle) {
- // summary: forms a y skewing matrix
- // description: The resulting matrix is used to skew points in
- // the y dimension
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an skewing angle in radians
- return new m.Matrix2D({
- yx : Math.tan(angle)
- }); // dojox.gfx.matrix.Matrix2D
- },
- skewYg : function(degree) {
- // summary: forms a y skewing matrix
- // description: The resulting matrix is used to skew points in
- // the y dimension
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.skewY() for comparison.
- // degree: Number: an skewing angle in degrees
- return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- reflect : function(a, b) {
- // summary: forms a reflection matrix
- // description: The resulting matrix is used to reflect points
- // around a vector,
- // which goes through the origin.
- // a: dojox.gfx.Point: a point-like object, which specifies a
- // vector of reflection
- // b: null
- if (arguments.length == 1) {
- b = a.y;
- a = a.x;
- }
- // branch
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- // make a unit vector
- var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
- return new m.Matrix2D({
- xx : 2 * a2 / n2 - 1,
- xy : xy,
- yx : xy,
- yy : 2 * b2 / n2 - 1
- }); // dojox.gfx.matrix.Matrix2D
- },
- project : function(a, b) {
- // summary: forms an orthogonal projection matrix
- // description: The resulting matrix is used to project points
- // orthogonally on a vector,
- // which goes through the origin.
- // a: dojox.gfx.Point: a point-like object, which specifies a
- // vector of projection
- // b: null
- if (arguments.length == 1) {
- b = a.y;
- a = a.x;
- }
- // branch
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- // make a unit vector
- var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
- return new m.Matrix2D({
- xx : a2 / n2,
- xy : xy,
- yx : xy,
- yy : b2 / n2
- }); // dojox.gfx.matrix.Matrix2D
- },
- // ensure matrix 2D conformance
- normalize : function(matrix) {
- // summary: converts an object to a matrix, if necessary
- // description: Converts any 2D matrix-like object or an array
- // of
- // such objects to a valid dojox.gfx.matrix.Matrix2D object.
- // matrix: Object: an object, which is converted to a matrix, if
- // necessary
- return (matrix instanceof m.Matrix2D)
- ? matrix
- : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
- },
- // common operations
- clone : function(matrix) {
- // summary: creates a copy of a 2D matrix
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to
- // be cloned
- var obj = new m.Matrix2D();
- for (var i in matrix) {
- if (typeof(matrix[i]) == "number"
- && typeof(obj[i]) == "number"
- && obj[i] != matrix[i])
- obj[i] = matrix[i];
- }
- return obj; // dojox.gfx.matrix.Matrix2D
- },
- invert : function(matrix) {
- // summary: inverts a 2D matrix
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to
- // be inverted
- var M = m.normalize(matrix), D = M.xx * M.yy - M.xy * M.yx, M = new m.Matrix2D(
- {
- xx : M.yy / D,
- xy : -M.xy / D,
- yx : -M.yx / D,
- yy : M.xx / D,
- dx : (M.xy * M.dy - M.yy * M.dx) / D,
- dy : (M.yx * M.dx - M.xx * M.dy) / D
- });
- return M; // dojox.gfx.matrix.Matrix2D
- },
- _multiplyPoint : function(matrix, x, y) {
- // summary: applies a matrix to a point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be
- // applied
- // x: Number: an x coordinate of a point
- // y: Number: a y coordinate of a point
- return {
- x : matrix.xx * x + matrix.xy * y + matrix.dx,
- y : matrix.yx * x + matrix.yy * y + matrix.dy
- }; // dojox.gfx.Point
- },
- multiplyPoint : function(matrix, /* Number||Point */a, /*
- * Number,
- * optional
- */
- b) {
- // summary: applies a matrix to a point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be
- // applied
- // a: Number: an x coordinate of a point
- // b: Number: a y coordinate of a point
- var M = m.normalize(matrix);
- if (typeof a == "number" && typeof b == "number") {
- return m._multiplyPoint(M, a, b); // dojox.gfx.Point
- }
- // branch
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be
- // applied
- // a: dojox.gfx.Point: a point
- // b: null
- return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
- },
- multiply : function(matrix) {
- // summary: combines matrices by multiplying them sequentially
- // in the given order
- // matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like
- // object,
- // all subsequent arguments are matrix-like objects too
- var M = m.normalize(matrix);
- // combine matrices
- for (var i = 1; i < arguments.length; ++i) {
- var l = M, r = m.normalize(arguments[i]);
- M = new m.Matrix2D();
- M.xx = l.xx * r.xx + l.xy * r.yx;
- M.xy = l.xx * r.xy + l.xy * r.yy;
- M.yx = l.yx * r.xx + l.yy * r.yx;
- M.yy = l.yx * r.xy + l.yy * r.yy;
- M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
- M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
- }
- return M; // dojox.gfx.matrix.Matrix2D
- },
- // high level operations
- _sandwich : function(matrix, x, y) {
- // summary: applies a matrix at a centrtal point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object,
- // which is applied at a central point
- // x: Number: an x component of the central point
- // y: Number: a y component of the central point
- return m.multiply(m.translate(x, y), matrix, m
- .translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
- },
- scaleAt : function(a, b, c, d) {
- // summary: scales a picture using a specified point as a center
- // of scaling
- // description: Compare with dojox.gfx.matrix.scale().
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- // c: Number: an x component of a central point
- // d: Number: a y component of a central point
- // accepts several signatures:
- // 1) uniform scale factor, Point
- // 2) uniform scale factor, x, y
- // 3) x scale, y scale, Point
- // 4) x scale, y scale, x, y
- switch (arguments.length) {
- case 4 :
- // a and b are scale factor components, c and d are
- // components of a point
- return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
- case 3 :
- if (typeof c == "number") {
- // branch
- // a: Number: a uniform scaling factor used for both
- // coordinates
- // b: Number: an x component of a central point
- // c: Number: a y component of a central point
- // d: null
- return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- // c: dojox.gfx.Point: a central point
- // d: null
- return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: Number: a uniform scaling factor used for both coordinates
- // b: dojox.gfx.Point: a central point
- // c: null
- // d: null
- return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
- },
- rotateAt : function(angle, a, b) {
- // summary: rotates a picture using a specified point as a
- // center of rotation
- // description: Compare with dojox.gfx.matrix.rotate().
- // angle: Number: an angle of rotation in radians (>0 for CW)
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) rotation angle in radians, Point
- // 2) rotation angle in radians, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an angle of rotation in radians (>0 for CCW)
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- rotategAt : function(degree, a, b) {
- // summary: rotates a picture using a specified point as a
- // center of rotation
- // description: Compare with dojox.gfx.matrix.rotateg().
- // degree: Number: an angle of rotation in degrees (>0 for CW)
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) rotation angle in degrees, Point
- // 2) rotation angle in degrees, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an angle of rotation in degrees (>0 for CCW)
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewXAt : function(angle, a, b) {
- // summary: skews a picture along the x axis using a specified
- // point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewX().
- // angle: Number: an skewing angle in radians
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in radians, Point
- // 2) skew angle in radians, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an skewing angle in radians
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewXgAt : function(degree, a, b) {
- // summary: skews a picture along the x axis using a specified
- // point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewXg().
- // degree: Number: an skewing angle in degrees
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in degrees, Point
- // 2) skew angle in degrees, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an skewing angle in degrees
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewYAt : function(angle, a, b) {
- // summary: skews a picture along the y axis using a specified
- // point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewY().
- // angle: Number: an skewing angle in radians
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in radians, Point
- // 2) skew angle in radians, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an skewing angle in radians
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewYgAt : function(/* Number */degree, /* Number||Point */a, /*
- * Number,
- * optional
- */
- b) {
- // summary: skews a picture along the y axis using a specified
- // point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewYg().
- // degree: Number: an skewing angle in degrees
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in degrees, Point
- // 2) skew angle in degrees, x, y
- if (arguments.length > 2) {
- return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an skewing angle in degrees
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- }
- // TODO: rect-to-rect mapping, scale-to-fit (isotropic and
- // anisotropic versions)
- });
- })();
- // propagate Matrix2D up
- dojox.gfx.Matrix2D = dojox.gfx.matrix.Matrix2D;
- }
|