1 package flare.vis.operator.distortion
3 import flash.geom.Rectangle;
6 * Computes a bifocal distortion of space, magnifying a focus region of space
7 * and uniformly demagnifying the rest of the space. The affect is akin to
8 * passing a magnifying glass over the data.
11 * For more details on this form of transformation, see Y. K. Leung and
12 * M. D. Apperley, "A Review and Taxonomy of Distortion-Oriented Presentation
13 * Techniques", in Transactions of Computer-Human Interaction (TOCHI),
14 * 1(2): 126-160 (1994). Available online at
15 * <a href="portal.acm.org/citation.cfm?id=180173&dl=ACM">
16 * portal.acm.org/citation.cfm?id=180173&dl=ACM</a>.
19 public class BifocalDistortion extends Distortion
21 private var _rx:Number;
22 private var _mx:Number;
23 private var _ry:Number;
24 private var _my:Number;
27 * <p>Create a new BifocalDistortion with the specified range and
28 * magnification along both axes.</p>
30 * <p><strong>NOTE:</strong>if the range value times the magnification
31 * value is greater than 1, the resulting distortion can exceed the
34 * @param xrange the range around the focus that should be magnified along
35 * the x direction. This specifies the horizontal size of the magnified
36 * focus region, and should be a value between 0 and 1, 0 indicating no
37 * focus region and 1 indicating the whole display.
38 * @param xmag how much magnification along the x direction should be used
40 * @param yrange the range around the focus that should be magnified along
41 * the y direction. This specifies the vertical size of the magnified
42 * focus region, and should be a value between 0 and 1, 0 indicating no
43 * focus region and 1 indicating the whole display.
44 * @param ymag how much magnification along the y direction should be used
47 public function BifocalDistortion(xRange:Number=0.1, xMagnify:Number=3,
48 yRange:Number=0.1, yMagnify:Number=3)
54 _distortX = !(_rx == 0 || _mx == 1.0);
55 _distortY = !(_ry == 0 || _my == 1.0);
59 protected override function xDistort(x:Number):Number
61 return bifocal(x, layoutAnchor.x, _rx, _mx, _b.left, _b.right);
65 protected override function yDistort(y:Number):Number
67 return bifocal(y, layoutAnchor.y, _ry, _my, _b.top, _b.bottom);
71 protected override function sizeDistort(bb:Rectangle, x:Number, y:Number):Number
73 var xmag:Boolean = false, ymag:Boolean = false;
74 var m:Number, c:Number, a:Number, min:Number, max:Number;
77 c = (bb.left+bb.right)/2;
81 m = c<a ? a-min : max-a;
82 if (m == 0) m = max-min;
83 xmag = (Math.abs(c-a) <= _rx*m )
87 c = (bb.top+bb.bottom)/2;
91 m = c<a ? a-min : max-a;
92 if (m == 0) m = max-min;
93 ymag = (Math.abs(c-a) <= _ry*m);
96 if (xmag && !_distortY) {
98 } else if (ymag && !_distortX) {
100 } else if (xmag && ymag) {
101 return Math.min(_mx, _my);
103 return Math.min((1-_rx*_mx)/(1-_rx), (1-_ry*_my)/(1-_ry));
107 private function bifocal(x:Number, a:Number, r:Number,
108 mag:Number, min:Number, max:Number):Number
110 var m:Number, v:Number, s:Number, bx:Number;
111 m = (x<a ? a-min : max-a);
112 if ( m == 0 ) m = max-min;
114 if ( Math.abs(v) <= s ) { // in focus
116 } else { // out of focus
118 x = ((Math.abs(v)-s) / m) * ((1-bx)/(1-r));
119 return (v<0?-1:1)*m*(x + bx) + a;
123 } // end of class BifocalDistortion