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