Mercurial > hg > digilib-old
comparison client/digitallibrary/jquery/dlGeometry.js @ 606:8204615dad77 jquery
geometry classes as extra file
author | robcast |
---|---|
date | Thu, 13 Jan 2011 14:52:13 +0100 |
parents | |
children | c2566e470569 |
comparison
equal
deleted
inserted
replaced
605:aee94e4a8c48 | 606:8204615dad77 |
---|---|
1 /* digilib geometry classes | |
2 * should be integrated into jquery.digilib.js | |
3 */ | |
4 | |
5 var dlGeometry = function() { | |
6 /* | |
7 * Size class | |
8 */ | |
9 var size = function (w, h) { | |
10 var that = { | |
11 width : parseFloat(w), | |
12 height : parseFloat(h) | |
13 }; | |
14 that.equals = function(other) { | |
15 return (this.width === other.width && this.height === other.height); | |
16 }; | |
17 that.toString = function() { | |
18 return (this.width + "x" + this.height); | |
19 }; | |
20 return that; | |
21 }; | |
22 | |
23 /* | |
24 * Position class | |
25 */ | |
26 var position = function (x, y) { | |
27 var that = { | |
28 x : parseFloat(x), | |
29 y : parseFloat(y) | |
30 }; | |
31 that.equals = function(other) { | |
32 return (this.x === other.x && this.y === other.y); | |
33 }; | |
34 that.toString = function() { | |
35 return (this.x + "," + this.y); | |
36 }; | |
37 return that; | |
38 }; | |
39 /* | |
40 * Rectangle class | |
41 */ | |
42 var rectangle = function (x, y, w, h) { | |
43 var that = {}; | |
44 if (typeof x === "object") { | |
45 // assume x and y are Position | |
46 that = { | |
47 x : x.x, | |
48 y : x.y, | |
49 width : y.x - x.x, | |
50 height : y.y - x.y | |
51 }; | |
52 } else { | |
53 that = { | |
54 x : parseFloat(x), | |
55 y : parseFloat(y), | |
56 width : parseFloat(w), | |
57 height : parseFloat(h) | |
58 }; | |
59 } | |
60 // returns a copy of this Rectangle | |
61 that.copy = function() { | |
62 return rectangle(this.x, this.y, this.width, this.height); | |
63 }; | |
64 // returns the position of this Rectangle | |
65 that.getPosition = function() { | |
66 return position(this.x, this.y); | |
67 }; | |
68 // returns the upper left corner position | |
69 that.getPt1 = that.getPosition; | |
70 // returns the lower right corner position of this Rectangle | |
71 that.getPt2 = function() { | |
72 return position(this.x + this.width, this.y + this.height); | |
73 }; | |
74 // sets the upper left corner to position pos | |
75 that.setPt1 = function(pos) { | |
76 this.x = pos.x; | |
77 this.y = pos.y; | |
78 return this; | |
79 }; | |
80 that.setPt2 = function(pos) { | |
81 // sets the lower right corner to position pos | |
82 this.width = pos.x - this.x; | |
83 this.height = pos.y - this.y; | |
84 return this; | |
85 }; | |
86 that.getCenter = function() { | |
87 // returns the center position of this Rectangle | |
88 return position(this.x + this.width / 2, this.y + this.height / 2); | |
89 }; | |
90 that.setCenter = function(pos) { | |
91 // moves this Rectangle's center to position pos | |
92 this.x = pos.x - this.width / 2; | |
93 this.y = pos.y - this.height / 2; | |
94 return this; | |
95 }; | |
96 that.getSize = function() { | |
97 // returns the size of this Rectangle | |
98 return size(this.width, this.height); | |
99 }; | |
100 that.equals = function(other) { | |
101 // equal props | |
102 var eq = (this.x === other.x && this.y === other.y && | |
103 this.width === other.width); | |
104 return eq; | |
105 }; | |
106 that.getArea = function() { | |
107 // returns the area of this Rectangle | |
108 return (this.width * this.height); | |
109 }; | |
110 that.normalize = function() { | |
111 // eliminates negative width and height | |
112 var p = this.getPt2(); | |
113 this.x = Math.min(this.x, p.x); | |
114 this.y = Math.min(this.y, p.y); | |
115 this.width = Math.abs(this.width); | |
116 this.height = Math.abs(this.height); | |
117 return this; | |
118 }; | |
119 that.containsPosition = function(pos) { | |
120 // returns if Position "pos" lies inside of this rectangle | |
121 var ct = ((pos.x >= this.x) && (pos.y >= this.y) && | |
122 (pos.x <= this.x + this.width) && (pos.y <= this.y + this.width)); | |
123 return ct; | |
124 }; | |
125 that.containsRect = function(rect) { | |
126 // returns if rectangle "rect" is contained in this rectangle | |
127 return (this.containsPosition(rect.getPt1()) && this.containsPosition(rect.getPt2())); | |
128 }; | |
129 that.stayInside = function(rect) { | |
130 // changes this rectangle's x/y values so it stays inside of rectangle rect | |
131 // keeping the proportions | |
132 if (this.x < rect.x) { | |
133 this.x = rect.x; | |
134 } | |
135 if (this.y < rect.y) { | |
136 this.y = rect.y; | |
137 } | |
138 if (this.x + this.width > rect.x + rect.width) { | |
139 this.x = rect.x + rect.width - this.width; | |
140 } | |
141 if (this.y + this.height > rect.y + rect.height) { | |
142 this.y = rect.y + rect.height - this.height; | |
143 } | |
144 return this; | |
145 }; | |
146 that.clipTo = function(rect) { | |
147 // clips this rectangle so it stays inside of rectangle rect | |
148 var p1 = rect.getPt1(); | |
149 var p2 = rect.getPt2(); | |
150 var this2 = this.getPt2(); | |
151 this.setPt1(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y))); | |
152 this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y))); | |
153 return this; | |
154 }; | |
155 that.intersect = function(rect) { | |
156 // returns the intersection of the given Rectangle and this one | |
157 // FIX ME: not really, it should return null if there is no overlap | |
158 var sec = rect.copy(); | |
159 if (sec.x < this.x) { | |
160 sec.width = sec.width - (this.x - sec.x); | |
161 sec.x = this.x; | |
162 } | |
163 if (sec.y < this.y) { | |
164 sec.height = sec.height - (this.y - sec.y); | |
165 sec.y = this.y; | |
166 } | |
167 if (sec.x + sec.width > this.x + this.width) { | |
168 sec.width = (this.x + this.width) - sec.x; | |
169 } | |
170 if (sec.y + sec.height > this.y + this.height) { | |
171 sec.height = (this.y + this.height) - sec.y; | |
172 } | |
173 return sec; | |
174 }; | |
175 that.fit = function(rect) { | |
176 // returns a Rectangle that fits into this one (by moving first) | |
177 var sec = rect.copy(); | |
178 sec.x = Math.max(sec.x, this.x); | |
179 sec.y = Math.max(sec.y, this.x); | |
180 if (sec.x + sec.width > this.x + this.width) { | |
181 sec.x = this.x + this.width - sec.width; | |
182 } | |
183 if (sec.y + sec.height > this.y + this.height) { | |
184 sec.y = this.y + this.height - sec.height; | |
185 } | |
186 return sec.intersect(this); | |
187 }; | |
188 that.toString = function() { | |
189 return this.width+"x"+this.height+"@"+this.x+","+this.y; | |
190 }; | |
191 return that; | |
192 }; | |
193 | |
194 /* | |
195 * Transform class | |
196 * | |
197 * defines a class of affine transformations | |
198 */ | |
199 var transform = function (spec) { | |
200 var that = { | |
201 m00 : spec.m00 || 1.0, | |
202 m01 : spec.m01 || 0.0, | |
203 m02 : spec.m02 || 0.0, | |
204 m10 : spec.m10 || 0.0, | |
205 m11 : spec.m11 || 1.0, | |
206 m12 : spec.m12 || 0.0, | |
207 m20 : spec.m20 || 0.0, | |
208 m21 : spec.m21 || 0.0, | |
209 m22 : spec.m22 || 1.0 | |
210 }; | |
211 that.concat = function(traf) { | |
212 // add Transform traf to this Transform | |
213 for (var i = 0; i < 3; i++) { | |
214 for (var j = 0; j < 3; j++) { | |
215 var c = 0.0; | |
216 for (var k = 0; k < 3; k++) { | |
217 c += traf["m"+i+k] * this["m"+k+j]; | |
218 } | |
219 this["m"+i+j] = c; | |
220 } | |
221 } | |
222 return this; | |
223 }; | |
224 that.transform = function(rect) { | |
225 // returns transformed Rectangle or Position with this Transform applied | |
226 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02; | |
227 var y = this.m10 * rect.x + this.m11 * rect.y + this.m12; | |
228 if (rect.width) { | |
229 // transform the other corner points | |
230 var pt2 = rect.getPt2(); | |
231 var x2 = this.m00 * pt2.x + this.m01 * pt2.y + this.m02; | |
232 var y2 = this.m10 * pt2.x + this.m11 * pt2.y + this.m12; | |
233 var width = x2 - x; | |
234 var height = y2 - y; | |
235 return rectangle(x, y, width, height); | |
236 } | |
237 return position(x, y); | |
238 }; | |
239 that.invtransform = function(rect) { | |
240 // returns transformed Rectangle or Position with the inverse of this Transform applied | |
241 var det = this.m00 * this.m11 - this.m01 * this.m10; | |
242 var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11 * this.m02 + this.m01 * this.m12) / det; | |
243 var y = (- this.m10 * rect.x + this.m00 * rect.y + this.m10 * this.m02 - this.m00 * this.m12) / det; | |
244 if (rect.width) { | |
245 // transform the other corner points | |
246 var pt2 = rect.getPt2(); | |
247 var x2 = (this.m11 * pt2.x - this.m01 * pt2.y - this.m11 * this.m02 + this.m01 * this.m12) / det; | |
248 var y2 = (- this.m10 * pt2.x + this.m00 * pt2.y + this.m10 * this.m02 - this.m00 * this.m12) / det; | |
249 var width = x2 - x; | |
250 var height = y2 - y; | |
251 return rectangle(x, y, width, height); | |
252 } | |
253 return position(x, y); | |
254 }; | |
255 that.getRotation = getRotation; | |
256 that.getTranslation = getTranslation; | |
257 that.getScale = getScale; | |
258 | |
259 return that; | |
260 }; | |
261 | |
262 transform.getRotation = function (angle, pos) { | |
263 // returns a Transform that is a rotation by angle degrees around [pos.x, pos.y] | |
264 if (angle !== 0) { | |
265 var t = 2.0 * Math.PI * parseFloat(angle) / 360.0; | |
266 var traf = { | |
267 m00 : Math.cos(t), | |
268 m01 : - Math.sin(t), | |
269 m10 : Math.sin(t), | |
270 m11 : Math.cos(t), | |
271 m02 : pos.x - pos.x * Math.cos(t) + pos.y * Math.sin(t), | |
272 m12 : pos.y - pos.x * Math.sin(t) - pos.y * Math.cos(t) | |
273 }; | |
274 return transform(traf); | |
275 } | |
276 return transform(); | |
277 }; | |
278 | |
279 transform.getTranslation = function (pos) { | |
280 // returns a Transform that is a translation by [pos.x, pos,y] | |
281 var traf = { | |
282 m02 : pos.x, | |
283 m12 : pos.y | |
284 }; | |
285 return transform(traf); | |
286 }; | |
287 | |
288 transform.getScale = function (size) { | |
289 // returns a Transform that is a scale by [size.width, size.height] | |
290 var traf = { | |
291 m00 : size.width, | |
292 m11 : size.height | |
293 }; | |
294 return transform(traf); | |
295 }; | |
296 | |
297 // export functions | |
298 var that = { | |
299 size : size, | |
300 position : position, | |
301 rectangle : rectangle, | |
302 transform : transform | |
303 }; | |
304 | |
305 return that; | |
306 }; |