source: other-projects/nz-flag-design/trunk/design-2d/Original editor.method.ac/editor/src/math.js@ 29468

Last change on this file since 29468 was 29468, checked in by sjs49, 9 years ago

Initial commit for editor.method.ac for flag design

  • Property svn:executable set to *
File size: 7.3 KB
Line 
1/**
2 * Package: svedit.math
3 *
4 * Licensed under the Apache License, Version 2
5 *
6 * Copyright(c) 2010 Alexis Deveria
7 * Copyright(c) 2010 Jeff Schiller
8 */
9
10// Dependencies:
11// None.
12
13var svgedit = svgedit || {};
14
15(function() {
16
17if (!svgedit.math) {
18 svgedit.math = {};
19}
20
21// Constants
22var NEAR_ZERO = 1e-14;
23
24// Throw away SVGSVGElement used for creating matrices/transforms.
25var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
26
27// Function: svgedit.math.transformPoint
28// A (hopefully) quicker function to transform a point by a matrix
29// (this function avoids any DOM calls and just does the math)
30//
31// Parameters:
32// x - Float representing the x coordinate
33// y - Float representing the y coordinate
34// m - Matrix object to transform the point with
35// Returns a x,y object representing the transformed point
36svgedit.math.transformPoint = function(x, y, m) {
37 return { x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};
38};
39
40
41// Function: svgedit.math.isIdentity
42// Helper function to check if the matrix performs no actual transform
43// (i.e. exists for identity purposes)
44//
45// Parameters:
46// m - The matrix object to check
47//
48// Returns:
49// Boolean indicating whether or not the matrix is 1,0,0,1,0,0
50svgedit.math.isIdentity = function(m) {
51 return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
52};
53
54
55// Function: svgedit.math.matrixMultiply
56// This function tries to return a SVGMatrix that is the multiplication m1*m2.
57// We also round to zero when it's near zero
58//
59// Parameters:
60// >= 2 Matrix objects to multiply
61//
62// Returns:
63// The matrix object resulting from the calculation
64svgedit.math.matrixMultiply = function() {
65 var args = arguments, i = args.length, m = args[i-1];
66
67 while(i-- > 1) {
68 var m1 = args[i-1];
69 m = m1.multiply(m);
70 }
71 if (Math.abs(m.a) < NEAR_ZERO) m.a = 0;
72 if (Math.abs(m.b) < NEAR_ZERO) m.b = 0;
73 if (Math.abs(m.c) < NEAR_ZERO) m.c = 0;
74 if (Math.abs(m.d) < NEAR_ZERO) m.d = 0;
75 if (Math.abs(m.e) < NEAR_ZERO) m.e = 0;
76 if (Math.abs(m.f) < NEAR_ZERO) m.f = 0;
77
78 return m;
79};
80
81// Function: svgedit.math.hasMatrixTransform
82// See if the given transformlist includes a non-indentity matrix transform
83//
84// Parameters:
85// tlist - The transformlist to check
86//
87// Returns:
88// Boolean on whether or not a matrix transform was found
89svgedit.math.hasMatrixTransform = function(tlist) {
90 if(!tlist) return false;
91 var num = tlist.numberOfItems;
92 while (num--) {
93 var xform = tlist.getItem(num);
94 if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) return true;
95 }
96 return false;
97};
98
99// Function: svgedit.math.transformBox
100// Transforms a rectangle based on the given matrix
101//
102// Parameters:
103// l - Float with the box's left coordinate
104// t - Float with the box's top coordinate
105// w - Float with the box width
106// h - Float with the box height
107// m - Matrix object to transform the box by
108//
109// Returns:
110// An object with the following values:
111// * tl - The top left coordinate (x,y object)
112// * tr - The top right coordinate (x,y object)
113// * bl - The bottom left coordinate (x,y object)
114// * br - The bottom right coordinate (x,y object)
115// * aabox - Object with the following values:
116// * Float with the axis-aligned x coordinate
117// * Float with the axis-aligned y coordinate
118// * Float with the axis-aligned width coordinate
119// * Float with the axis-aligned height coordinate
120svgedit.math.transformBox = function(l, t, w, h, m) {
121 var topleft = {x:l,y:t},
122 topright = {x:(l+w),y:t},
123 botright = {x:(l+w),y:(t+h)},
124 botleft = {x:l,y:(t+h)};
125 var transformPoint = svgedit.math.transformPoint;
126 topleft = transformPoint( topleft.x, topleft.y, m );
127 var minx = topleft.x,
128 maxx = topleft.x,
129 miny = topleft.y,
130 maxy = topleft.y;
131 topright = transformPoint( topright.x, topright.y, m );
132 minx = Math.min(minx, topright.x);
133 maxx = Math.max(maxx, topright.x);
134 miny = Math.min(miny, topright.y);
135 maxy = Math.max(maxy, topright.y);
136 botleft = transformPoint( botleft.x, botleft.y, m);
137 minx = Math.min(minx, botleft.x);
138 maxx = Math.max(maxx, botleft.x);
139 miny = Math.min(miny, botleft.y);
140 maxy = Math.max(maxy, botleft.y);
141 botright = transformPoint( botright.x, botright.y, m );
142 minx = Math.min(minx, botright.x);
143 maxx = Math.max(maxx, botright.x);
144 miny = Math.min(miny, botright.y);
145 maxy = Math.max(maxy, botright.y);
146
147 return {tl:topleft, tr:topright, bl:botleft, br:botright,
148 aabox: {x:minx, y:miny, width:(maxx-minx), height:(maxy-miny)} };
149};
150
151// Function: svgedit.math.transformListToTransform
152// This returns a single matrix Transform for a given Transform List
153// (this is the equivalent of SVGTransformList.consolidate() but unlike
154// that method, this one does not modify the actual SVGTransformList)
155// This function is very liberal with its min,max arguments
156//
157// Parameters:
158// tlist - The transformlist object
159// min - Optional integer indicating start transform position
160// max - Optional integer indicating end transform position
161//
162// Returns:
163// A single matrix transform object
164svgedit.math.transformListToTransform = function(tlist, min, max) {
165 if(tlist == null) {
166 // Or should tlist = null have been prevented before this?
167 return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());
168 }
169 var min = min == undefined ? 0 : min;
170 var max = max == undefined ? (tlist.numberOfItems-1) : max;
171 min = parseInt(min);
172 max = parseInt(max);
173 if (min > max) { var temp = max; max = min; min = temp; }
174 var m = svg.createSVGMatrix();
175 for (var i = min; i <= max; ++i) {
176 // if our indices are out of range, just use a harmless identity matrix
177 var mtom = (i >= 0 && i < tlist.numberOfItems ?
178 tlist.getItem(i).matrix :
179 svg.createSVGMatrix());
180 m = svgedit.math.matrixMultiply(m, mtom);
181 }
182 return svg.createSVGTransformFromMatrix(m);
183};
184
185
186// Function: svgedit.math.getMatrix
187// Get the matrix object for a given element
188//
189// Parameters:
190// elem - The DOM element to check
191//
192// Returns:
193// The matrix object associated with the element's transformlist
194svgedit.math.getMatrix = function(elem) {
195 var tlist = svgedit.transformlist.getTransformList(elem);
196 return svgedit.math.transformListToTransform(tlist).matrix;
197};
198
199
200// Function: svgedit.math.snapToAngle
201// Returns a 45 degree angle coordinate associated with the two given
202// coordinates
203//
204// Parameters:
205// x1 - First coordinate's x value
206// x2 - Second coordinate's x value
207// y1 - First coordinate's y value
208// y2 - Second coordinate's y value
209//
210// Returns:
211// Object with the following values:
212// x - The angle-snapped x value
213// y - The angle-snapped y value
214// snapangle - The angle at which to snap
215svgedit.math.snapToAngle = function(x1,y1,x2,y2) {
216 var snap = Math.PI/4; // 45 degrees
217 var dx = x2 - x1;
218 var dy = y2 - y1;
219 var angle = Math.atan2(dy,dx);
220 var dist = Math.sqrt(dx * dx + dy * dy);
221 var snapangle= Math.round(angle/snap)*snap;
222 var x = x1 + dist*Math.cos(snapangle);
223 var y = y1 + dist*Math.sin(snapangle);
224 //console.log(x1,y1,x2,y2,x,y,angle)
225 return {x:x, y:y, a:snapangle};
226};
227
228
229// Function: rectsIntersect
230// Check if two rectangles (BBoxes objects) intersect each other
231//
232// Paramaters:
233// r1 - The first BBox-like object
234// r2 - The second BBox-like object
235//
236// Returns:
237// Boolean that's true if rectangles intersect
238svgedit.math.rectsIntersect = function(r1, r2) {
239 if (!r1 || !r2) return false;
240 return r2.x < (r1.x+r1.width) &&
241 (r2.x+r2.width) > r1.x &&
242 r2.y < (r1.y+r1.height) &&
243 (r2.y+r2.height) > r1.y;
244};
245
246
247})();
Note: See TracBrowser for help on using the repository browser.