Mercurial > hg > digilib
annotate client/digitallibrary/jquery/dlGeometry.js @ 665:0d3d9517e448 jquery
image transform works now under rotation!!! (at least for multiples of 90deg)
rectangle has adjustDiv to postition and size a jQuery object
rectangle constructor with two positions always returns a rectangle with positive width
| author | robcast |
|---|---|
| date | Tue, 25 Jan 2011 17:47:36 +0100 |
| parents | dcd64ecdd64a |
| children | 9f8056d6c289 |
| 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 } | |
| 599 | 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") { | |
| 647 | 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 = { | |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
74 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
|
75 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
|
76 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
|
77 height : Math.abs(y.y - x.y) |
| 647 | 78 }; |
| 79 } | |
| 599 | 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) && | |
| 647 | 150 (pos.x <= this.x + this.width) && (pos.y <= this.y + this.height)); |
| 599 | 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 }; | |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
216 // 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
|
217 that.adjustDiv = function ($elem) { |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
218 $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
|
219 $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
|
220 }; |
| 599 | 221 that.toString = function() { |
| 222 return this.width+"x"+this.height+"@"+this.x+","+this.y; | |
| 223 }; | |
| 224 return that; | |
| 225 }; | |
| 226 | |
| 227 /* | |
| 228 * Transform class | |
| 229 * | |
| 230 * defines a class of affine transformations | |
| 231 */ | |
| 232 var transform = function (spec) { | |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
233 var that = { |
| 620 | 234 m00 : 1.0, |
| 235 m01 : 0.0, | |
| 236 m02 : 0.0, | |
| 237 m10 : 0.0, | |
| 238 m11 : 1.0, | |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
239 m12 : 0.0, |
| 620 | 240 m20 : 0.0, |
| 241 m21 : 0.0, | |
| 242 m22 : 1.0 | |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
243 }; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
244 if (spec) { |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
245 jQuery.extend(that, spec); |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
246 }; |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
247 that.concat = function(trafA) { |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
248 // 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
|
249 var trafC = {}; |
| 599 | 250 for (var i = 0; i < 3; i++) { |
| 251 for (var j = 0; j < 3; j++) { | |
| 252 var c = 0.0; | |
| 253 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
|
254 c += trafA["m"+i+k] * this["m"+k+j]; |
| 599 | 255 } |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
256 trafC["m"+i+j] = c; |
| 599 | 257 } |
| 258 } | |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
259 jQuery.extend(this, trafC); |
| 599 | 260 return this; |
| 261 }; | |
| 262 that.transform = function(rect) { | |
| 263 // returns transformed Rectangle or Position with this Transform applied | |
| 264 var x = this.m00 * rect.x + this.m01 * rect.y + this.m02; | |
| 265 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
|
266 var pt = position(x, y); |
| 599 | 267 if (rect.width) { |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
268 // transform the other corner point |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
269 var pt2 = this.transform(rect.getPt2()); |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
270 return rectangle(pt, pt2); |
| 599 | 271 } |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
272 return pt; |
| 599 | 273 }; |
| 274 that.invtransform = function(rect) { | |
| 275 // returns transformed Rectangle or Position with the inverse of this Transform applied | |
| 276 var det = this.m00 * this.m11 - this.m01 * this.m10; | |
| 277 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
|
278 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
|
279 var pt = position(x, y); |
| 599 | 280 if (rect.width) { |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
281 // transform the other corner point |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
282 var pt2 = this.invtransform(rect.getPt2()); |
|
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
283 return rectangle(pt, pt2); |
| 599 | 284 } |
|
665
0d3d9517e448
image transform works now under rotation!!! (at least for multiples of 90deg)
robcast
parents:
664
diff
changeset
|
285 return pt; |
| 599 | 286 }; |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
287 that.toString = function (pretty) { |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
288 var s = '['; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
289 if (pretty) s += '\n'; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
290 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
|
291 s += '['; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
292 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
|
293 if (j) s += ','; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
294 s += this['m'+i+j]; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
295 } |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
296 s += ']'; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
297 if (pretty) s += '\n'; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
298 } |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
299 s += ']'; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
300 if (pretty) s += '\n'; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
301 return s; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
302 }; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
303 // add class methods to instance |
| 620 | 304 that.getRotation = transform.getRotation; |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
305 that.getRotationAround = transform.getRotationAround; |
| 620 | 306 that.getTranslation = transform.getTranslation; |
| 307 that.getScale = transform.getScale; | |
| 648 | 308 |
| 599 | 309 return that; |
| 310 }; | |
| 311 | |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
312 transform.getRotation = function (angle) { |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
313 // returns a Transform that is a rotation by angle degrees around [0,0] |
| 599 | 314 if (angle !== 0) { |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
315 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
|
316 var cost = Math.cos(t); |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
317 var sint = Math.sin(t); |
| 599 | 318 var traf = { |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
319 m00 : cost, |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
320 m01 : -sint, |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
321 m10 : sint, |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
322 m11 : cost |
| 599 | 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 | |
|
657
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
338 transform.getRotationAround = function (angle, pos) { |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
339 // returns a Transform that is a rotation by angle degrees around pos |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
340 var traf = transform.getTranslation({x : -pos.x, y : -pos.y}); |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
341 traf.concat(transform.getRotation(angle)); |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
342 traf.concat(transform.getTranslation(pos)); |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
343 return traf; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
344 }; |
|
b0c6cc4a0932
work on getting transformation to work with rotation (currently still doesn't)
robcast
parents:
649
diff
changeset
|
345 |
| 599 | 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 }; |
