source: Dev/branches/rest-dojo-ui/client/dojox/gfx/matrix.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 16.7 KB
Line 
1define(["./_base","dojo/_base/lang"],
2  function(g, lang){
3        var m = g.matrix = {};
4        /*===== g = dojox.gfx; m = dojox.gfx.matrix =====*/
5
6        // candidates for dojox.math:
7        var _degToRadCache = {};
8        m._degToRad = function(degree){
9                return _degToRadCache[degree] || (_degToRadCache[degree] = (Math.PI * degree / 180));
10        };
11        m._radToDeg = function(radian){ return radian / Math.PI * 180; };
12
13        m.Matrix2D = function(arg){
14                // summary:
15                //              a 2D matrix object
16                // description: Normalizes a 2D matrix-like object. If arrays is passed,
17                //              all objects of the array are normalized and multiplied sequentially.
18                // arg: Object
19                //              a 2D matrix-like object, a number, or an array of such objects
20                if(arg){
21                        if(typeof arg == "number"){
22                                this.xx = this.yy = arg;
23                        }else if(arg instanceof Array){
24                                if(arg.length > 0){
25                                        var matrix = m.normalize(arg[0]);
26                                        // combine matrices
27                                        for(var i = 1; i < arg.length; ++i){
28                                                var l = matrix, r = m.normalize(arg[i]);
29                                                matrix = new m.Matrix2D();
30                                                matrix.xx = l.xx * r.xx + l.xy * r.yx;
31                                                matrix.xy = l.xx * r.xy + l.xy * r.yy;
32                                                matrix.yx = l.yx * r.xx + l.yy * r.yx;
33                                                matrix.yy = l.yx * r.xy + l.yy * r.yy;
34                                                matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
35                                                matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
36                                        }
37                                        lang.mixin(this, matrix);
38                                }
39                        }else{
40                                lang.mixin(this, arg);
41                        }
42                }
43        };
44
45        // the default (identity) matrix, which is used to fill in missing values
46        lang.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
47
48        lang.mixin(m, {
49                // summary: class constants, and methods of dojox.gfx.matrix
50
51                // matrix constants
52
53                // identity: dojox.gfx.matrix.Matrix2D
54                //              an identity matrix constant: identity * (x, y) == (x, y)
55                identity: new m.Matrix2D(),
56
57                // flipX: dojox.gfx.matrix.Matrix2D
58                //              a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
59                flipX:    new m.Matrix2D({xx: -1}),
60
61                // flipY: dojox.gfx.matrix.Matrix2D
62                //              a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
63                flipY:    new m.Matrix2D({yy: -1}),
64
65                // flipXY: dojox.gfx.matrix.Matrix2D
66                //              a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
67                flipXY:   new m.Matrix2D({xx: -1, yy: -1}),
68
69                // matrix creators
70
71                translate: function(a, b){
72                        // summary: forms a translation matrix
73                        // description: The resulting matrix is used to translate (move) points by specified offsets.
74                        // a: Number: an x coordinate value
75                        // b: Number: a y coordinate value
76                        if(arguments.length > 1){
77                                return new m.Matrix2D({dx: a, dy: b}); // dojox.gfx.matrix.Matrix2D
78                        }
79                        // branch
80                        // a: dojox.gfx.Point: a point-like object, which specifies offsets for both dimensions
81                        // b: null
82                        return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox.gfx.matrix.Matrix2D
83                },
84                scale: function(a, b){
85                        // summary: forms a scaling matrix
86                        // description: The resulting matrix is used to scale (magnify) points by specified offsets.
87                        // a: Number: a scaling factor used for the x coordinate
88                        // b: Number: a scaling factor used for the y coordinate
89                        if(arguments.length > 1){
90                                return new m.Matrix2D({xx: a, yy: b}); // dojox.gfx.matrix.Matrix2D
91                        }
92                        if(typeof a == "number"){
93                                // branch
94                                // a: Number: a uniform scaling factor used for the both coordinates
95                                // b: null
96                                return new m.Matrix2D({xx: a, yy: a}); // dojox.gfx.matrix.Matrix2D
97                        }
98                        // branch
99                        // a: dojox.gfx.Point: a point-like object, which specifies scale factors for both dimensions
100                        // b: null
101                        return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox.gfx.matrix.Matrix2D
102                },
103                rotate: function(angle){
104                        // summary: forms a rotating matrix
105                        // description: The resulting matrix is used to rotate points
106                        //              around the origin of coordinates (0, 0) by specified angle.
107                        // angle: Number: an angle of rotation in radians (>0 for CW)
108                        var c = Math.cos(angle);
109                        var s = Math.sin(angle);
110                        return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx.matrix.Matrix2D
111                },
112                rotateg: function(degree){
113                        // summary: forms a rotating matrix
114                        // description: The resulting matrix is used to rotate points
115                        //              around the origin of coordinates (0, 0) by specified degree.
116                        //              See dojox.gfx.matrix.rotate() for comparison.
117                        // degree: Number: an angle of rotation in degrees (>0 for CW)
118                        return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
119                },
120                skewX: function(angle) {
121                        // summary: forms an x skewing matrix
122                        // description: The resulting matrix is used to skew points in the x dimension
123                        //              around the origin of coordinates (0, 0) by specified angle.
124                        // angle: Number: an skewing angle in radians
125                        return new m.Matrix2D({xy: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
126                },
127                skewXg: function(degree){
128                        // summary: forms an x skewing matrix
129                        // description: The resulting matrix is used to skew points in the x dimension
130                        //              around the origin of coordinates (0, 0) by specified degree.
131                        //              See dojox.gfx.matrix.skewX() for comparison.
132                        // degree: Number: an skewing angle in degrees
133                        return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
134                },
135                skewY: function(angle){
136                        // summary: forms a y skewing matrix
137                        // description: The resulting matrix is used to skew points in the y dimension
138                        //              around the origin of coordinates (0, 0) by specified angle.
139                        // angle: Number: an skewing angle in radians
140                        return new m.Matrix2D({yx: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
141                },
142                skewYg: function(degree){
143                        // summary: forms a y skewing matrix
144                        // description: The resulting matrix is used to skew points in the y dimension
145                        //              around the origin of coordinates (0, 0) by specified degree.
146                        //              See dojox.gfx.matrix.skewY() for comparison.
147                        // degree: Number: an skewing angle in degrees
148                        return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
149                },
150                reflect: function(a, b){
151                        // summary: forms a reflection matrix
152                        // description: The resulting matrix is used to reflect points around a vector,
153                        //              which goes through the origin.
154                        // a: dojox.gfx.Point: a point-like object, which specifies a vector of reflection
155                        // b: null
156                        if(arguments.length == 1){
157                                b = a.y;
158                                a = a.x;
159                        }
160                        // branch
161                        // a: Number: an x coordinate value
162                        // b: Number: a y coordinate value
163
164                        // make a unit vector
165                        var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
166                        return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox.gfx.matrix.Matrix2D
167                },
168                project: function(a, b){
169                        // summary: forms an orthogonal projection matrix
170                        // description: The resulting matrix is used to project points orthogonally on a vector,
171                        //              which goes through the origin.
172                        // a: dojox.gfx.Point: a point-like object, which specifies a vector of projection
173                        // b: null
174                        if(arguments.length == 1){
175                                b = a.y;
176                                a = a.x;
177                        }
178                        // branch
179                        // a: Number: an x coordinate value
180                        // b: Number: a y coordinate value
181
182                        // make a unit vector
183                        var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
184                        return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox.gfx.matrix.Matrix2D
185                },
186
187                // ensure matrix 2D conformance
188                normalize: function(matrix){
189                        // summary: converts an object to a matrix, if necessary
190                        // description: Converts any 2D matrix-like object or an array of
191                        //              such objects to a valid dojox.gfx.matrix.Matrix2D object.
192                        // matrix: Object: an object, which is converted to a matrix, if necessary
193                        return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
194                },
195
196                // common operations
197
198                clone: function(matrix){
199                        // summary: creates a copy of a 2D matrix
200                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be cloned
201                        var obj = new m.Matrix2D();
202                        for(var i in matrix){
203                                if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
204                        }
205                        return obj; // dojox.gfx.matrix.Matrix2D
206                },
207                invert: function(matrix){
208                        // summary: inverts a 2D matrix
209                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be inverted
210                        var M = m.normalize(matrix),
211                                D = M.xx * M.yy - M.xy * M.yx;
212                                M = new m.Matrix2D({
213                                        xx: M.yy/D, xy: -M.xy/D,
214                                        yx: -M.yx/D, yy: M.xx/D,
215                                        dx: (M.xy * M.dy - M.yy * M.dx) / D,
216                                        dy: (M.yx * M.dx - M.xx * M.dy) / D
217                                });
218                        return M; // dojox.gfx.matrix.Matrix2D
219                },
220                _multiplyPoint: function(matrix, x, y){
221                        // summary: applies a matrix to a point
222                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
223                        // x: Number: an x coordinate of a point
224                        // y: Number: a y coordinate of a point
225                        return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox.gfx.Point
226                },
227                multiplyPoint: function(matrix, /* Number||Point */ a, /* Number? */ b){
228                        // summary: applies a matrix to a point
229                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
230                        // a: Number: an x coordinate of a point
231                        // b: Number?: a y coordinate of a point
232                        var M = m.normalize(matrix);
233                        if(typeof a == "number" && typeof b == "number"){
234                                return m._multiplyPoint(M, a, b); // dojox.gfx.Point
235                        }
236                        // branch
237                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
238                        // a: dojox.gfx.Point: a point
239                        // b: null
240                        return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
241                },
242                multiply: function(matrix){
243                        // summary: combines matrices by multiplying them sequentially in the given order
244                        // matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like object,
245                        //              all subsequent arguments are matrix-like objects too
246                        var M = m.normalize(matrix);
247                        // combine matrices
248                        for(var i = 1; i < arguments.length; ++i){
249                                var l = M, r = m.normalize(arguments[i]);
250                                M = new m.Matrix2D();
251                                M.xx = l.xx * r.xx + l.xy * r.yx;
252                                M.xy = l.xx * r.xy + l.xy * r.yy;
253                                M.yx = l.yx * r.xx + l.yy * r.yx;
254                                M.yy = l.yx * r.xy + l.yy * r.yy;
255                                M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
256                                M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
257                        }
258                        return M; // dojox.gfx.matrix.Matrix2D
259                },
260
261                // high level operations
262
263                _sandwich: function(matrix, x, y){
264                        // summary: applies a matrix at a centrtal point
265                        // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object, which is applied at a central point
266                        // x: Number: an x component of the central point
267                        // y: Number: a y component of the central point
268                        return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
269                },
270                scaleAt: function(a, b, c, d){
271                        // summary: scales a picture using a specified point as a center of scaling
272                        // description: Compare with dojox.gfx.matrix.scale().
273                        // a: Number: a scaling factor used for the x coordinate
274                        // b: Number: a scaling factor used for the y coordinate
275                        // c: Number: an x component of a central point
276                        // d: Number: a y component of a central point
277
278                        // accepts several signatures:
279                        //      1) uniform scale factor, Point
280                        //      2) uniform scale factor, x, y
281                        //      3) x scale, y scale, Point
282                        //      4) x scale, y scale, x, y
283
284                        switch(arguments.length){
285                                case 4:
286                                        // a and b are scale factor components, c and d are components of a point
287                                        return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
288                                case 3:
289                                        if(typeof c == "number"){
290                                                // branch
291                                                // a: Number: a uniform scaling factor used for both coordinates
292                                                // b: Number: an x component of a central point
293                                                // c: Number: a y component of a central point
294                                                // d: null
295                                                return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
296                                        }
297                                        // branch
298                                        // a: Number: a scaling factor used for the x coordinate
299                                        // b: Number: a scaling factor used for the y coordinate
300                                        // c: dojox.gfx.Point: a central point
301                                        // d: null
302                                        return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
303                        }
304                        // branch
305                        // a: Number: a uniform scaling factor used for both coordinates
306                        // b: dojox.gfx.Point: a central point
307                        // c: null
308                        // d: null
309                        return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
310                },
311                rotateAt: function(angle, a, b){
312                        // summary: rotates a picture using a specified point as a center of rotation
313                        // description: Compare with dojox.gfx.matrix.rotate().
314                        // angle: Number: an angle of rotation in radians (>0 for CW)
315                        // a: Number: an x component of a central point
316                        // b: Number: a y component of a central point
317
318                        // accepts several signatures:
319                        //      1) rotation angle in radians, Point
320                        //      2) rotation angle in radians, x, y
321
322                        if(arguments.length > 2){
323                                return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
324                        }
325
326                        // branch
327                        // angle: Number: an angle of rotation in radians (>0 for CCW)
328                        // a: dojox.gfx.Point: a central point
329                        // b: null
330                        return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
331                },
332                rotategAt: function(degree, a, b){
333                        // summary: rotates a picture using a specified point as a center of rotation
334                        // description: Compare with dojox.gfx.matrix.rotateg().
335                        // degree: Number: an angle of rotation in degrees (>0 for CW)
336                        // a: Number: an x component of a central point
337                        // b: Number: a y component of a central point
338
339                        // accepts several signatures:
340                        //      1) rotation angle in degrees, Point
341                        //      2) rotation angle in degrees, x, y
342
343                        if(arguments.length > 2){
344                                return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
345                        }
346
347                        // branch
348                        // degree: Number: an angle of rotation in degrees (>0 for CCW)
349                        // a: dojox.gfx.Point: a central point
350                        // b: null
351                        return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
352                },
353                skewXAt: function(angle, a, b){
354                        // summary: skews a picture along the x axis using a specified point as a center of skewing
355                        // description: Compare with dojox.gfx.matrix.skewX().
356                        // angle: Number: an skewing angle in radians
357                        // a: Number: an x component of a central point
358                        // b: Number: a y component of a central point
359
360                        // accepts several signatures:
361                        //      1) skew angle in radians, Point
362                        //      2) skew angle in radians, x, y
363
364                        if(arguments.length > 2){
365                                return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
366                        }
367
368                        // branch
369                        // angle: Number: an skewing angle in radians
370                        // a: dojox.gfx.Point: a central point
371                        // b: null
372                        return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
373                },
374                skewXgAt: function(degree, a, b){
375                        // summary: skews a picture along the x axis using a specified point as a center of skewing
376                        // description: Compare with dojox.gfx.matrix.skewXg().
377                        // degree: Number: an skewing angle in degrees
378                        // a: Number: an x component of a central point
379                        // b: Number: a y component of a central point
380
381                        // accepts several signatures:
382                        //      1) skew angle in degrees, Point
383                        //      2) skew angle in degrees, x, y
384
385                        if(arguments.length > 2){
386                                return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
387                        }
388
389                        // branch
390                        // degree: Number: an skewing angle in degrees
391                        // a: dojox.gfx.Point: a central point
392                        // b: null
393                        return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
394                },
395                skewYAt: function(angle, a, b){
396                        // summary: skews a picture along the y axis using a specified point as a center of skewing
397                        // description: Compare with dojox.gfx.matrix.skewY().
398                        // angle: Number: an skewing angle in radians
399                        // a: Number: an x component of a central point
400                        // b: Number: a y component of a central point
401
402                        // accepts several signatures:
403                        //      1) skew angle in radians, Point
404                        //      2) skew angle in radians, x, y
405
406                        if(arguments.length > 2){
407                                return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
408                        }
409
410                        // branch
411                        // angle: Number: an skewing angle in radians
412                        // a: dojox.gfx.Point: a central point
413                        // b: null
414                        return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
415                },
416                skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number? */ b){
417                        // summary: skews a picture along the y axis using a specified point as a center of skewing
418                        // description: Compare with dojox.gfx.matrix.skewYg().
419                        // degree: Number: an skewing angle in degrees
420                        // a: Number: an x component of a central point
421                        // b: Number?: a y component of a central point
422
423                        // accepts several signatures:
424                        //      1) skew angle in degrees, Point
425                        //      2) skew angle in degrees, x, y
426
427                        if(arguments.length > 2){
428                                return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
429                        }
430
431                        // branch
432                        // degree: Number: an skewing angle in degrees
433                        // a: dojox.gfx.Point: a central point
434                        // b: null
435                        return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
436                }
437
438                //TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
439
440        });
441        // propagate Matrix2D up
442        g.Matrix2D = m.Matrix2D;
443
444        return m;
445});
446
447
Note: See TracBrowser for help on using the repository browser.