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