Mercurial > hg > digilib-old
annotate webapp/src/main/webapp/jquery/jquery.digilib.geometry.js @ 1113:7affda55c10e
using annotator in digilib works somewhat now.
author | robcast |
---|---|
date | Thu, 01 Nov 2012 18:38:11 +0100 |
parents | 1e4f4964e9c2 |
children | efe4b0f18cf8 |
rev | line source |
---|---|
785 | 1 /** required digilib geometry plugin |
2 */ | |
3 | |
4 (function($) { | |
5 //var dlGeometry = function() { | |
6 /* | |
7 * Size class | |
8 */ | |
9 var size = function(w, h) { | |
10 var that; | |
11 if (typeof w === "object") { | |
1012 | 12 // assume an object having width and height |
785 | 13 that = { |
14 width : w.width, | |
15 height : w.height | |
16 }; | |
17 } else { | |
18 that = { | |
19 width : parseFloat(w), | |
20 height : parseFloat(h) | |
21 }; | |
22 } | |
1012 | 23 // returns true if both sizes are equal |
785 | 24 that.equals = function(other) { |
25 return (this.width === other.width && this.height === other.height); | |
26 }; | |
1012 | 27 // returns the aspect ratio of this size |
28 that.getAspect = function() { | |
29 return (this.width / this.height); | |
30 }; | |
31 // returns a size of a given aspect ratio that fits into this one | |
32 that.fitAspect = function(aspect) { | |
33 var s = size(this); | |
34 if (aspect > this.getAspect()) { | |
35 // size is more horizontally stretched than this | |
36 s.height = s.width / aspect; | |
37 } else { | |
38 s.width = s.height * aspect; | |
39 } | |
40 return s; | |
41 }; | |
957 | 42 // adjusts size of jQuery element "$elem" to this size |
43 that.adjustDiv = function($elem) { | |
44 $elem.width(this.width).height(this.height); | |
45 }; | |
785 | 46 that.toString = function() { |
47 return (this.width + "x" + this.height); | |
48 }; | |
49 return that; | |
50 }; | |
51 | |
52 /* | |
53 * Position class | |
54 */ | |
55 var position = function(x, y) { | |
56 var that; | |
57 if (typeof x === "object") { | |
58 if (x instanceof jQuery) { | |
59 // jQuery object | |
60 var pos = x.offset(); | |
61 that = { | |
62 x : pos.left, | |
63 y : pos.top | |
64 }; | |
65 } else { | |
66 if (x.x != null) { | |
67 // position object | |
68 that = { | |
69 x : x.x, | |
70 y : x.y | |
71 }; | |
72 } | |
73 if (x.pageX != null) { | |
74 // event object | |
75 that = { | |
76 x : x.pageX, | |
77 y : x.pageY | |
78 }; | |
79 } | |
80 } | |
81 } else { | |
82 that = { | |
83 x : parseFloat(x), | |
84 y : parseFloat(y) | |
85 }; | |
86 } | |
87 that.equals = function(other) { | |
88 return (this.x === other.x && this.y === other.y); | |
89 }; | |
90 // add position other to this | |
91 that.add = function(other) { | |
92 this.x += other.x; | |
93 this.y += other.y; | |
94 return this; | |
95 }; | |
96 // returns negative position | |
97 that.neg = function() { | |
98 return position({ | |
99 x : -this.x, | |
100 y : -this.y | |
101 }); | |
102 }; | |
103 // returns new position that is the difference between this and other | |
104 that.delta = function(other) { | |
105 return position({ | |
106 x : other.x - this.x, | |
107 y : other.y - this.y | |
108 }); | |
109 }; | |
944 | 110 // adjusts CSS position of $elem to this position |
785 | 111 that.adjustDiv = function($elem) { |
112 $elem.offset({ | |
113 left : this.x, | |
114 top : this.y | |
115 }); | |
116 }; | |
117 // returns distance of this position to pos (length if pos == null) | |
118 that.distance = function(pos) { | |
119 if (pos == null) { | |
120 pos = { | |
121 x : 0, | |
122 y : 0 | |
123 }; | |
124 } | |
125 var dx = pos.x - this.x; | |
126 var dy = pos.y - this.y; | |
127 return Math.sqrt(dx * dx + dy * dy); | |
128 }; | |
1113 | 129 // returns position in css-compatible format |
130 that.getAsCss = function() { | |
131 return { | |
132 left : this.x, | |
133 top : this.y, | |
134 }; | |
135 }; | |
785 | 136 that.toString = function() { |
137 return (this.x + "," + this.y); | |
138 }; | |
139 return that; | |
140 }; | |
141 /* | |
142 * Rectangle class | |
143 */ | |
144 var rectangle = function(x, y, w, h) { | |
145 var that = {}; | |
146 if (typeof x === "object") { | |
147 if (x instanceof jQuery) { | |
148 // jQuery object | |
149 var pos = x.offset(); | |
150 that = { | |
151 x : pos.left, | |
152 y : pos.top, | |
153 width : x.width(), | |
154 height : x.height() | |
155 }; | |
156 } else if (y == null) { | |
157 // assume x is rectangle | |
158 that = { | |
974 | 159 x : x.x || 0, |
160 y : x.y || 0, | |
161 width : x.width || 0, | |
162 height : x.height || 0 | |
785 | 163 }; |
164 } else { | |
165 // assume x and y are Position | |
166 that = { | |
167 x : Math.min(x.x, y.x), | |
168 y : Math.min(x.y, y.y), | |
169 width : Math.abs(y.x - x.x), | |
170 height : Math.abs(y.y - x.y) | |
171 }; | |
172 } | |
173 } else { | |
174 that = { | |
175 x : parseFloat(x), | |
176 y : parseFloat(y), | |
177 width : parseFloat(w), | |
178 height : parseFloat(h) | |
179 }; | |
180 } | |
181 // returns a copy of this Rectangle | |
182 that.copy = function() { | |
183 return rectangle(this); | |
184 }; | |
185 // returns the position of this Rectangle | |
186 that.getPosition = function() { | |
187 return position(this); | |
188 }; | |
189 // returns the size of this Rectangle | |
190 that.getSize = function() { | |
191 return size(this); | |
192 }; | |
193 // returns the upper left corner position | |
194 that.getPt1 = that.getPosition; | |
195 // returns the lower right corner position of this Rectangle | |
196 that.getPt2 = function() { | |
197 return position({ | |
198 x : this.x + this.width, | |
199 y : this.y + this.height | |
200 }); | |
201 }; | |
202 // sets the upper left corner position to pos | |
203 that.setPosition = function(pos) { | |
204 this.x = pos.x; | |
205 this.y = pos.y; | |
206 return this; | |
207 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
208 // adds pos to the position |
785 | 209 that.setPt1 = that.setPosition; // TODO: not really the same |
210 that.addPosition = function(pos) { | |
211 this.x += pos.x; | |
212 this.y += pos.y; | |
213 return this; | |
214 }; | |
877 | 215 // adds pos to the dimensions |
216 that.enlarge = function(pos) { | |
217 this.width += pos.x; | |
218 this.height += pos.y; | |
219 return this; | |
220 }; | |
785 | 221 // sets the lower right corner to position pos |
222 that.setPt2 = function(pos) { | |
223 this.width = pos.x - this.x; | |
224 this.height = pos.y - this.y; | |
225 return this; | |
226 }; | |
227 // returns the center position of this Rectangle | |
228 that.getCenter = function() { | |
229 return position({ | |
230 x : this.x + this.width / 2, | |
231 y : this.y + this.height / 2 | |
232 }); | |
233 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
234 // moves this rectangle's center to position pos |
785 | 235 that.setCenter = function(pos) { |
236 this.x = pos.x - this.width / 2; | |
237 this.y = pos.y - this.height / 2; | |
238 return this; | |
239 }; | |
944 | 240 // returns true if both rectangles have equal position and size |
785 | 241 that.equals = function(other) { |
242 var eq = (this.x === other.x && this.y === other.y && this.width === other.width); | |
243 return eq; | |
244 }; | |
944 | 245 // returns a rectangle with the difference width, height and position |
246 that.delta = function(other) { | |
247 return rectangle(other.x - this.x, other.y - this.y, | |
248 other.width - this.width, other.height - this.height); | |
249 }; | |
785 | 250 // returns the area of this Rectangle |
251 that.getArea = function() { | |
252 return (this.width * this.height); | |
253 }; | |
953
3d5e7458f9ae
fixed birdseye region positioning after layout reflow.
robcast
parents:
944
diff
changeset
|
254 // returns the aspect ratio of this Rectangle |
3d5e7458f9ae
fixed birdseye region positioning after layout reflow.
robcast
parents:
944
diff
changeset
|
255 that.getAspect = function() { |
3d5e7458f9ae
fixed birdseye region positioning after layout reflow.
robcast
parents:
944
diff
changeset
|
256 return (this.width / this.height); |
3d5e7458f9ae
fixed birdseye region positioning after layout reflow.
robcast
parents:
944
diff
changeset
|
257 }; |
785 | 258 // eliminates negative width and height |
259 that.normalize = function() { | |
260 var p = this.getPt2(); | |
261 this.x = Math.min(this.x, p.x); | |
262 this.y = Math.min(this.y, p.y); | |
263 this.width = Math.abs(this.width); | |
264 this.height = Math.abs(this.height); | |
265 return this; | |
266 }; | |
267 // returns if Position "pos" lies inside of this rectangle | |
268 that.containsPosition = function(pos) { | |
269 var ct = ((pos.x >= this.x) && (pos.y >= this.y) | |
270 && (pos.x <= this.x + this.width) && (pos.y <= this.y | |
271 + this.height)); | |
272 return ct; | |
273 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
274 // returns true if rectangle "rect" is contained in this rectangle |
785 | 275 that.containsRect = function(rect) { |
276 return (this.containsPosition(rect.getPt1()) && this | |
277 .containsPosition(rect.getPt2())); | |
278 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
279 // returns true if rectangle "rect" and this rectangle overlap |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
280 that.overlapsRect = function(rect) { |
812 | 281 return this.intersect(rect) != null; |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
282 }; |
785 | 283 // changes this rectangle's x/y values so it stays inside of rectangle |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
284 // "rect", keeping the proportions |
785 | 285 that.stayInside = function(rect) { |
812 | 286 this.x = Math.max(this.x, rect.x); |
287 this.y = Math.max(this.y, rect.y); | |
785 | 288 if (this.x + this.width > rect.x + rect.width) { |
289 this.x = rect.x + rect.width - this.width; | |
290 } | |
291 if (this.y + this.height > rect.y + rect.height) { | |
292 this.y = rect.y + rect.height - this.height; | |
293 } | |
294 return this; | |
295 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
296 // clips this rectangle so it stays inside of rectangle "rect" |
785 | 297 that.clipTo = function(rect) { |
298 var p1 = rect.getPt1(); | |
299 var p2 = rect.getPt2(); | |
300 var this2 = this.getPt2(); | |
301 this.setPosition(position(Math.max(this.x, p1.x), Math.max(this.y, p1.y))); | |
302 this.setPt2(position(Math.min(this2.x, p2.x), Math.min(this2.y, p2.y))); | |
303 return this; | |
304 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
305 // returns the intersection of rectangle "rect" and this one |
785 | 306 that.intersect = function(rect) { |
847 | 307 var r = rect.copy(); |
308 var result = r.clipTo(this); | |
309 if (result.width < 0 || result.height < 0) result = null; | |
310 return result; | |
785 | 311 }; |
812 | 312 |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
313 // returns a copy of rectangle "rect" that fits into this one |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
314 // (moving it first) |
785 | 315 that.fit = function(rect) { |
847 | 316 var r = rect.copy(); |
317 r.x = Math.max(r.x, this.x); | |
318 r.y = Math.max(r.y, this.x); | |
319 if (r.x + r.width > this.x + this.width) { | |
320 r.x = this.x + this.width - r.width; | |
785 | 321 } |
847 | 322 if (r.y + r.height > this.y + this.height) { |
323 r.y = this.y + this.height - r.height; | |
785 | 324 } |
847 | 325 return r.intersect(this); |
785 | 326 }; |
1012 | 327 |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
328 // adjusts position and size of jQuery element "$elem" to this rectangle |
785 | 329 that.adjustDiv = function($elem) { |
330 $elem.offset({ | |
331 left : this.x, | |
332 top : this.y | |
333 }); | |
334 $elem.width(this.width).height(this.height); | |
335 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
336 // returns position and size of this rectangle in css-compatible format |
785 | 337 that.getAsCss = function() { |
338 return { | |
339 left : this.x, | |
340 top : this.y, | |
341 width : this.width, | |
342 height : this.height | |
343 }; | |
344 }; | |
807
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
345 // returns position and size of this rectangle formatted for SVG attributes |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
346 that.getAsSvg = function() { |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
347 return [this.x, this.y, this.width, this.height].join(" "); |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
348 }; |
1b1728926534
geometry: overlapsRect() plus some comment clarifications
hertzhaft
parents:
793
diff
changeset
|
349 // returns size and position of this rectangle formatted for ??? (w x h@x,y) |
785 | 350 that.toString = function() { |
351 return this.width + "x" + this.height + "@" + this.x + "," + this.y; | |
352 }; | |
353 return that; | |
354 }; | |
355 | |
356 /* | |
357 * Transform class | |
358 * | |
359 * defines a class of affine transformations | |
360 */ | |
361 var transform = function(spec) { | |
362 var that = { | |
363 m00 : 1.0, | |
364 m01 : 0.0, | |
365 m02 : 0.0, | |
366 m10 : 0.0, | |
367 m11 : 1.0, | |
368 m12 : 0.0, | |
369 m20 : 0.0, | |
370 m21 : 0.0, | |
371 m22 : 1.0 | |
372 }; | |
373 if (spec) { | |
374 jQuery.extend(that, spec); | |
375 } | |
376 ; | |
377 that.concat = function(trafA) { | |
1075
1e4f4964e9c2
CLOSED - # 25: scroll arrows have wrong direction with mirror and rot
robcast
parents:
1012
diff
changeset
|
378 // add Transform trafA to this Transform (i.e. this = trafC = trafA * this) |
785 | 379 var trafC = {}; |
380 for ( var i = 0; i < 3; i++) { | |
381 for ( var j = 0; j < 3; j++) { | |
382 var c = 0.0; | |
383 for ( var k = 0; k < 3; k++) { | |
384 c += trafA["m" + i + k] * this["m" + k + j]; | |
385 } | |
386 trafC["m" + i + j] = c; | |
387 } | |
388 } | |
389 jQuery.extend(this, trafC); | |
390 return this; | |
391 }; | |
392 that.transform = function(rect) { | |
393 // returns transformed Rectangle or Position with this Transform | |
394 // applied | |
395 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02; | |
396 var y = this.m10 * rect.x + this.m11 * rect.y + this.m12; | |
397 var pt = position(x, y); | |
398 if (rect.width) { | |
399 // transform the other corner point | |
400 var pt2 = this.transform(rect.getPt2()); | |
401 return rectangle(pt, pt2); | |
402 } | |
403 return pt; | |
404 }; | |
405 that.invtransform = function(rect) { | |
406 // returns transformed Rectangle or Position with the inverse of | |
407 // this Transform applied | |
408 var det = this.m00 * this.m11 - this.m01 * this.m10; | |
409 var x = (this.m11 * rect.x - this.m01 * rect.y - this.m11 | |
410 * this.m02 + this.m01 * this.m12) | |
411 / det; | |
412 var y = (-this.m10 * rect.x + this.m00 * rect.y + this.m10 | |
413 * this.m02 - this.m00 * this.m12) | |
414 / det; | |
415 var pt = position(x, y); | |
416 if (rect.width) { | |
417 // transform the other corner point | |
418 var pt2 = this.invtransform(rect.getPt2()); | |
419 return rectangle(pt, pt2); | |
420 } | |
421 return pt; | |
422 }; | |
423 that.toString = function(pretty) { | |
424 var s = '['; | |
425 if (pretty) | |
426 s += '\n'; | |
427 for ( var i = 0; i < 3; ++i) { | |
428 s += '['; | |
429 for ( var j = 0; j < 3; ++j) { | |
430 if (j) | |
431 s += ','; | |
432 s += this['m' + i + j]; | |
433 } | |
434 s += ']'; | |
435 if (pretty) | |
436 s += '\n'; | |
437 } | |
438 s += ']'; | |
439 if (pretty) | |
440 s += '\n'; | |
441 return s; | |
442 }; | |
443 // add class methods to instance | |
444 that.getRotation = transform.getRotation; | |
445 that.getRotationAround = transform.getRotationAround; | |
446 that.getTranslation = transform.getTranslation; | |
447 that.getMirror = transform.getMirror; | |
448 that.getScale = transform.getScale; | |
449 | |
450 return that; | |
451 }; | |
452 | |
453 transform.getRotation = function(angle) { | |
454 // returns a Transform that is a rotation by angle degrees around [0,0] | |
455 if (angle !== 0) { | |
456 var t = Math.PI * parseFloat(angle) / 180.0; | |
457 var cost = Math.cos(t); | |
458 var sint = Math.sin(t); | |
459 var traf = { | |
460 m00 : cost, | |
461 m01 : -sint, | |
462 m10 : sint, | |
463 m11 : cost | |
464 }; | |
465 return transform(traf); | |
466 } | |
467 return transform(); | |
468 }; | |
469 | |
470 transform.getRotationAround = function(angle, pos) { | |
471 // returns a Transform that is a rotation by angle degrees around pos | |
472 var traf = transform.getTranslation(pos.neg()); | |
473 traf.concat(transform.getRotation(angle)); | |
474 traf.concat(transform.getTranslation(pos)); | |
475 return traf; | |
476 }; | |
477 | |
478 transform.getTranslation = function(pos) { | |
479 // returns a Transform that is a translation by [pos.x, pos,y] | |
480 var traf = { | |
481 m02 : pos.x, | |
482 m12 : pos.y | |
483 }; | |
484 return transform(traf); | |
485 }; | |
486 | |
487 transform.getMirror = function(type) { | |
488 // returns a Transform that is a mirror about the axis type | |
489 if (type === 'x') { | |
490 var traf = { | |
491 m00 : 1, | |
492 m11 : -1 | |
493 }; | |
494 } else { | |
495 var traf = { | |
496 m00 : -1, | |
497 m11 : 1 | |
498 }; | |
499 } | |
500 return transform(traf); | |
501 }; | |
502 | |
503 transform.getScale = function(size) { | |
504 // returns a Transform that is a scale by [size.width, size.height] | |
505 var traf = { | |
506 m00 : size.width, | |
507 m11 : size.height | |
508 }; | |
509 return transform(traf); | |
510 }; | |
511 | |
786 | 512 // export constructor functions to digilib plugin |
793
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
513 var geometry = { |
786 | 514 size : size, |
515 position : position, | |
516 rectangle : rectangle, | |
517 transform : transform | |
793
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
518 }; |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
519 // install function called by digilib on plugin object |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
520 var install = function() { |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
521 // add constructor object to fn |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
522 this.fn.geometry = geometry; |
785 | 523 }; |
793
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
524 // digilib plugin object |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
525 var plugin = { |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
526 name : 'geometry', |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
527 install : install, |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
528 fn : {}, |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
529 // TODO: remove old init |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
530 init : init |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
531 }; |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
532 // TODO: remove old version of init returning contructor |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
533 var init = function () { |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
534 return geometry; |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
535 }; |
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
536 // plug into digilib |
786 | 537 if ($.fn.digilib == null) { |
538 $.error("jquery.digilib.geometry must be loaded after jquery.digilib!"); | |
539 } else { | |
793
63c1b33e38b1
documentation for new plugin api in jquery-digilib-plugin.txt.
robcast
parents:
788
diff
changeset
|
540 $.fn.digilib('plugin', plugin); |
786 | 541 } |
785 | 542 })(jQuery); |