Mercurial > hg > digilib-old
annotate client/digitallibrary/jquery/dlGeometry.js @ 671:a53c3e12995a jquery
still working on correct transform for rotations... (still doesn't)
author | robcast |
---|---|
date | Tue, 25 Jan 2011 11:01:45 +0100 |
parents | d5a5ee4cbf04 |
children | 7f7536a5b6d9 |
rev | line source |
---|---|
606 | 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) { | |
654 | 27 if (typeof x === "object") { |
28 if (x instanceof jQuery) { | |
29 // jQuery object | |
30 var pos = x.offset(); | |
31 var that = { | |
32 x : pos.left, | |
33 y : pos.top | |
34 }; | |
35 } else { | |
36 // event object(?) | |
37 var that = { | |
38 x : x.pageX, | |
39 y : x.pageY | |
40 }; | |
41 } | |
42 } else { | |
43 var that = { | |
44 x : parseFloat(x), | |
45 y : parseFloat(y) | |
46 }; | |
47 } | |
606 | 48 that.equals = function(other) { |
49 return (this.x === other.x && this.y === other.y); | |
50 }; | |
51 that.toString = function() { | |
52 return (this.x + "," + this.y); | |
53 }; | |
54 return that; | |
55 }; | |
56 /* | |
57 * Rectangle class | |
58 */ | |
59 var rectangle = function (x, y, w, h) { | |
60 var that = {}; | |
61 if (typeof x === "object") { | |
654 | 62 if (x instanceof jQuery) { |
63 // jQuery object | |
64 var pos = x.offset(); | |
65 that = { | |
66 x : pos.left, | |
67 y : pos.top, | |
68 width : x.width(), | |
69 height : x.height() | |
70 }; | |
71 } else { | |
72 // assume x and y are Position | |
73 that = { | |
74 x : x.x, | |
75 y : x.y, | |
76 width : y.x - x.x, | |
77 height : y.y - x.y | |
78 }; | |
79 } | |
606 | 80 } else { |
81 that = { | |
82 x : parseFloat(x), | |
83 y : parseFloat(y), | |
84 width : parseFloat(w), | |
85 height : parseFloat(h) | |
86 }; | |
87 } | |
88 // returns a copy of this Rectangle | |
89 that.copy = function() { | |
90 return rectangle(this.x, this.y, this.width, this.height); | |
91 }; | |
92 // returns the position of this Rectangle | |
93 that.getPosition = function() { | |
94 return position(this.x, this.y); | |
95 }; | |
96 // returns the upper left corner position | |
97 that.getPt1 = that.getPosition; | |
98 // returns the lower right corner position of this Rectangle | |
99 that.getPt2 = function() { | |
100 return position(this.x + this.width, this.y + this.height); | |
101 }; | |
102 // sets the upper left corner to position pos | |
103 that.setPt1 = function(pos) { | |
104 this.x = pos.x; | |
105 this.y = pos.y; | |
106 return this; | |
107 }; | |
108 that.setPt2 = function(pos) { | |
109 // sets the lower right corner to position pos | |
110 this.width = pos.x - this.x; | |
111 this.height = pos.y - this.y; | |
112 return this; | |
113 }; | |
114 that.getCenter = function() { | |
115 // returns the center position of this Rectangle | |
116 return position(this.x + this.width / 2, this.y + this.height / 2); | |
117 }; | |
118 that.setCenter = function(pos) { | |
119 // moves this Rectangle's center to position pos | |
120 this.x = pos.x - this.width / 2; | |
121 this.y = pos.y - this.height / 2; | |
122 return this; | |
123 }; | |
124 that.getSize = function() { | |
125 // returns the size of this Rectangle | |
126 return size(this.width, this.height); | |
127 }; | |
128 that.equals = function(other) { | |
129 // equal props | |
130 var eq = (this.x === other.x && this.y === other.y && | |
131 this.width === other.width); | |
132 return eq; | |
133 }; | |
134 that.getArea = function() { | |
135 // returns the area of this Rectangle | |
136 return (this.width * this.height); | |
137 }; | |
138 that.normalize = function() { | |
139 // eliminates negative width and height | |
140 var p = this.getPt2(); | |
141 this.x = Math.min(this.x, p.x); | |
142 this.y = Math.min(this.y, p.y); | |
143 this.width = Math.abs(this.width); | |
144 this.height = Math.abs(this.height); | |
145 return this; | |
146 }; | |
147 that.containsPosition = function(pos) { | |
148 // returns if Position "pos" lies inside of this rectangle | |
149 var ct = ((pos.x >= this.x) && (pos.y >= this.y) && | |
654 | 150 (pos.x <= this.x + this.width) && (pos.y <= this.y + this.height)); |
606 | 151 return ct; |
152 }; | |
153 that.containsRect = function(rect) { | |
154 // returns if rectangle "rect" is contained in this rectangle | |
155 return (this.containsPosition(rect.getPt1()) && this.containsPosition(rect.getPt2())); | |
156 }; | |
157 that.stayInside = function(rect) { | |
158 // changes this rectangle's x/y values so it stays inside of rectangle rect | |
159 // keeping the proportions | |
160 if (this.x < rect.x) { | |
161 this.x = rect.x; | |
162 } | |
163 if (this.y < rect.y) { | |
164 this.y = rect.y; | |
165 } | |
166 if (this.x + this.width > rect.x + rect.width) { | |
167 this.x = rect.x + rect.width - this.width; | |
168 } | |
169 if (this.y + this.height > rect.y + rect.height) { | |
170 this.y = rect.y + rect.height - this.height; | |
171 } | |
172 return this; | |
173 }; | |
174 that.clipTo = function(rect) { | |
175 // clips this rectangle so it stays inside of rectangle rect | |
176 var p1 = rect.getPt1(); | |
177 var p2 = rect.getPt2(); | |
178 var this2 = this.getPt2(); | |
179 this.setPt1(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y))); | |
180 this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y))); | |
181 return this; | |
182 }; | |
183 that.intersect = function(rect) { | |
184 // returns the intersection of the given Rectangle and this one | |
185 // FIX ME: not really, it should return null if there is no overlap | |
186 var sec = rect.copy(); | |
187 if (sec.x < this.x) { | |
188 sec.width = sec.width - (this.x - sec.x); | |
189 sec.x = this.x; | |
190 } | |
191 if (sec.y < this.y) { | |
192 sec.height = sec.height - (this.y - sec.y); | |
193 sec.y = this.y; | |
194 } | |
195 if (sec.x + sec.width > this.x + this.width) { | |
196 sec.width = (this.x + this.width) - sec.x; | |
197 } | |
198 if (sec.y + sec.height > this.y + this.height) { | |
199 sec.height = (this.y + this.height) - sec.y; | |
200 } | |
201 return sec; | |
202 }; | |
203 that.fit = function(rect) { | |
204 // returns a Rectangle that fits into this one (by moving first) | |
205 var sec = rect.copy(); | |
206 sec.x = Math.max(sec.x, this.x); | |
207 sec.y = Math.max(sec.y, this.x); | |
208 if (sec.x + sec.width > this.x + this.width) { | |
209 sec.x = this.x + this.width - sec.width; | |
210 } | |
211 if (sec.y + sec.height > this.y + this.height) { | |
212 sec.y = this.y + this.height - sec.height; | |
213 } | |
214 return sec.intersect(this); | |
215 }; | |
216 that.toString = function() { | |
217 return this.width+"x"+this.height+"@"+this.x+","+this.y; | |
218 }; | |
219 return that; | |
220 }; | |
221 | |
222 /* | |
223 * Transform class | |
224 * | |
225 * defines a class of affine transformations | |
226 */ | |
227 var transform = function (spec) { | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
228 var that = { |
627 | 229 m00 : 1.0, |
230 m01 : 0.0, | |
231 m02 : 0.0, | |
232 m10 : 0.0, | |
233 m11 : 1.0, | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
234 m12 : 0.0, |
627 | 235 m20 : 0.0, |
236 m21 : 0.0, | |
237 m22 : 1.0 | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
238 }; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
239 if (spec) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
240 jQuery.extend(that, spec); |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
241 }; |
606 | 242 that.concat = function(traf) { |
243 // add Transform traf to this Transform | |
244 for (var i = 0; i < 3; i++) { | |
245 for (var j = 0; j < 3; j++) { | |
246 var c = 0.0; | |
247 for (var k = 0; k < 3; k++) { | |
671
a53c3e12995a
still working on correct transform for rotations... (still doesn't)
robcast
parents:
664
diff
changeset
|
248 c += traf["m"+i+k] * this["m"+k+j]; |
a53c3e12995a
still working on correct transform for rotations... (still doesn't)
robcast
parents:
664
diff
changeset
|
249 //c += this["m"+i.toString()+k.toString()] * traf["m"+k.toString()+j.toString()]; |
606 | 250 } |
671
a53c3e12995a
still working on correct transform for rotations... (still doesn't)
robcast
parents:
664
diff
changeset
|
251 this["m"+i+j] = c; |
606 | 252 } |
253 } | |
254 return this; | |
255 }; | |
256 that.transform = function(rect) { | |
257 // returns transformed Rectangle or Position with this Transform applied | |
258 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02; | |
259 var y = this.m10 * rect.x + this.m11 * rect.y + this.m12; | |
260 if (rect.width) { | |
261 // transform the other corner points | |
262 var pt2 = rect.getPt2(); | |
263 var x2 = this.m00 * pt2.x + this.m01 * pt2.y + this.m02; | |
264 var y2 = this.m10 * pt2.x + this.m11 * pt2.y + this.m12; | |
265 var width = x2 - x; | |
266 var height = y2 - y; | |
267 return rectangle(x, y, width, height); | |
268 } | |
269 return position(x, y); | |
270 }; | |
271 that.invtransform = function(rect) { | |
272 // returns transformed Rectangle or Position with the inverse of this Transform applied | |
273 var det = this.m00 * this.m11 - this.m01 * this.m10; | |
274 var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11 * this.m02 + this.m01 * this.m12) / det; | |
275 var y = (- this.m10 * rect.x + this.m00 * rect.y + this.m10 * this.m02 - this.m00 * this.m12) / det; | |
276 if (rect.width) { | |
277 // transform the other corner points | |
278 var pt2 = rect.getPt2(); | |
279 var x2 = (this.m11 * pt2.x - this.m01 * pt2.y - this.m11 * this.m02 + this.m01 * this.m12) / det; | |
280 var y2 = (- this.m10 * pt2.x + this.m00 * pt2.y + this.m10 * this.m02 - this.m00 * this.m12) / det; | |
281 var width = x2 - x; | |
282 var height = y2 - y; | |
283 return rectangle(x, y, width, height); | |
284 } | |
285 return position(x, y); | |
286 }; | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
287 that.toString = function (pretty) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
288 var s = '['; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
289 if (pretty) s += '\n'; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
290 for (var i = 0; i < 3; ++i) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
291 s += '['; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
292 for (var j = 0; j < 3; ++j) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
293 if (j) s += ','; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
294 s += this['m'+i+j]; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
295 } |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
296 s += ']'; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
297 if (pretty) s += '\n'; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
298 } |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
299 s += ']'; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
300 if (pretty) s += '\n'; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
301 return s; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
302 }; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
303 // add class methods to instance |
627 | 304 that.getRotation = transform.getRotation; |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
305 that.getRotationAround = transform.getRotationAround; |
627 | 306 that.getTranslation = transform.getTranslation; |
307 that.getScale = transform.getScale; | |
655 | 308 |
606 | 309 return that; |
310 }; | |
311 | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
312 transform.getRotation = function (angle) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
313 // returns a Transform that is a rotation by angle degrees around [0,0] |
606 | 314 if (angle !== 0) { |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
315 var t = Math.PI * parseFloat(angle) / 180.0; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
316 var cost = Math.cos(t); |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
317 var sint = Math.sin(t); |
606 | 318 var traf = { |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
319 m00 : cost, |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
320 m01 : -sint, |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
321 m10 : sint, |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
322 m11 : cost |
606 | 323 }; |
324 return transform(traf); | |
325 } | |
326 return transform(); | |
327 }; | |
328 | |
329 transform.getTranslation = function (pos) { | |
330 // returns a Transform that is a translation by [pos.x, pos,y] | |
331 var traf = { | |
332 m02 : pos.x, | |
333 m12 : pos.y | |
334 }; | |
335 return transform(traf); | |
336 }; | |
337 | |
664
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
338 transform.getRotationAround = function (angle, pos) { |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
339 // returns a Transform that is a rotation by angle degrees around pos |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
340 var traf = transform.getTranslation({x : -pos.x, y : -pos.y}); |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
341 traf.concat(transform.getRotation(angle)); |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
342 traf.concat(transform.getTranslation(pos)); |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
343 return traf; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
344 }; |
d5a5ee4cbf04
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
656
diff
changeset
|
345 |
606 | 346 transform.getScale = function (size) { |
347 // returns a Transform that is a scale by [size.width, size.height] | |
348 var traf = { | |
349 m00 : size.width, | |
350 m11 : size.height | |
351 }; | |
352 return transform(traf); | |
353 }; | |
354 | |
355 // export functions | |
356 var that = { | |
357 size : size, | |
358 position : position, | |
359 rectangle : rectangle, | |
360 transform : transform | |
361 }; | |
362 | |
363 return that; | |
364 }; |