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