]> git.mjollnir.org Git - moodle.git/blob
e63db2b5ab29e6878f86944598b7b5b994450dde
[moodle.git] /
1 package flare.vis.operator.distortion
2 {
3         import flash.geom.Rectangle;
4         
5         /**
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.
9          * 
10          * <p>
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>.
17          * </p>
18          */
19         public class BifocalDistortion extends Distortion
20         {
21                 private var _rx:Number;
22                 private var _mx:Number;
23                 private var _ry:Number;
24                 private var _my:Number;
25                 
26                 /**
27              * <p>Create a new BifocalDistortion with the specified range and 
28              * magnification along both axes.</p>
29              * 
30              * <p><strong>NOTE:</strong>if the range value times the magnification
31              * value is greater than 1, the resulting distortion can exceed the
32              * display bounds.</p>
33              * 
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
39              *  in the focal area
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
45              *  in the focal area
46              */
47                 public function BifocalDistortion(xRange:Number=0.1, xMagnify:Number=3,
48                         yRange:Number=0.1, yMagnify:Number=3)
49                 {
50                         _rx = xRange;
51                 _mx = xMagnify;
52                 _ry = yRange;
53                 _my = yMagnify;
54                 _distortX = !(_rx == 0 || _mx == 1.0);
55                 _distortY = !(_ry == 0 || _my == 1.0);
56                 }
57                 
58                 /** @inheritDoc */
59                 protected override function xDistort(x:Number):Number
60                 {
61                         return bifocal(x, layoutAnchor.x, _rx, _mx, _b.left, _b.right); 
62                 }
63                 
64                 /** @inheritDoc */
65                 protected override function yDistort(y:Number):Number
66                 {
67                         return bifocal(y, layoutAnchor.y, _ry, _my, _b.top, _b.bottom); 
68                 }
69                 
70                 /** @inheritDoc */
71                 protected override function sizeDistort(bb:Rectangle, x:Number, y:Number):Number
72                 {
73                         var xmag:Boolean = false, ymag:Boolean = false;
74                         var m:Number, c:Number, a:Number, min:Number, max:Number;
75         
76                 if (_distortX) {
77                     c = (bb.left+bb.right)/2;
78                     a = layoutAnchor.x;
79                     min = _b.left;
80                     max = _b.right;
81                     m = c<a ? a-min : max-a;
82                     if (m == 0) m = max-min;
83                     xmag = (Math.abs(c-a) <= _rx*m )
84                 }
85                 
86                 if (_distortY) {
87                     c = (bb.top+bb.bottom)/2;
88                     a = layoutAnchor.y;
89                     min = _b.top;
90                     max = _b.bottom;
91                     m = c<a ? a-min : max-a;
92                     if (m == 0) m = max-min;
93                     ymag = (Math.abs(c-a) <= _ry*m);
94                 }
95                 
96                 if (xmag && !_distortY) {
97                     return _mx;
98                 } else if (ymag && !_distortX) {
99                     return _my;
100                 } else if (xmag && ymag) {
101                     return Math.min(_mx, _my);
102                 } else {
103                     return Math.min((1-_rx*_mx)/(1-_rx), (1-_ry*_my)/(1-_ry));
104                 }
105                 }
106                 
107                 private function bifocal(x:Number, a:Number, r:Number, 
108                            mag:Number, min:Number, max:Number):Number
109             {
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;
113                 v = x - a, s = m*r;
114                 if ( Math.abs(v) <= s ) {  // in focus
115                     return v*mag + a;
116                 } else {                   // out of focus
117                     bx = r*mag;
118                     x = ((Math.abs(v)-s) / m) * ((1-bx)/(1-r));
119                     return (v<0?-1:1)*m*(x + bx) + a;
120                 }
121             }
122                 
123         } // end of class BifocalDistortion
124 }