Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 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
}