package flare.vis.operator.distortion { import flash.geom.Rectangle; /** * Computes a graphical fisheye distortion of a graph view. This distortion * allocates more space to items near the layout anchor and less space to * items further away, magnifying space near the anchor and demagnifying * distant space in a continuous fashion. * *

* For more details on this form of transformation, see Manojit Sarkar and * Marc H. Brown, "Graphical Fisheye Views of Graphs", in Proceedings of * CHI'92, Human Factors in Computing Systems, p. 83-91, 1992. Available * online at * http://citeseer.ist.psu.edu/sarkar92graphical.html. *

*/ public class FisheyeDistortion extends Distortion { private var _dx:Number; // x distortion factor private var _dy:Number; // y distortion factor private var _ds:Number; // size distortion factor // -------------------------------------------------------------------- /** * Create a new FisheyeDistortion with the given distortion factors * along the x and y directions. * @param dx the distortion factor along the x axis (0 for none) * @param dy the distortion factor along the y axis (0 for none) * @param ds the distortion factor to use for sizes (0 for none) */ public function FisheyeDistortion(dx:Number=4, dy:Number=4, ds:Number=3) { _dx = dx; _dy = dy; _ds = ds; super(_dx>0, _dy>0, _ds>0); } /** @inheritDoc */ protected override function xDistort(x:Number):Number { return fisheye(x, layoutAnchor.x, _dx, _b.left, _b.right); } /** @inheritDoc */ protected override function yDistort(y:Number):Number { return fisheye(y, layoutAnchor.y, _dy, _b.top, _b.bottom); } /** @inheritDoc */ protected override function sizeDistort(bb:Rectangle, x:Number, y:Number):Number { if (!distortX && !distortY) return 1; var fx:Number=1, fy:Number=1; var a:Number, min:Number, max:Number, v:Number; if (distortX) { a = layoutAnchor.x; min = bb.left; max = bb.right; v = Math.abs(min-a) > Math.abs(max-a) ? min : max; if (v < _b.left || v > _b.right) v = (v==min ? max : min); fx = fisheye(v, a, _dx, _b.left, _b.right); fx = Math.abs(x-fx) / (max - min); } if (distortY) { a = layoutAnchor.y; min = bb.top; max = bb.bottom; v = Math.abs(min-a) > Math.abs(max-a) ? min : max; if (v < _b.top || v > _b.bottom) v = (v==min ? max : min); fy = fisheye(v, a, _dy, _b.top, _b.bottom); fy = Math.abs(y-fy) / (max - min); } var sf:Number = (!distortY ? fx : (!distortX ? fy : Math.min(fx,fy))); return (!isFinite(sf) || isNaN(sf)) ? 1 : _ds * sf; } private function fisheye(x:Number, a:Number, d:Number, min:Number, max:Number) : Number { if (d == 0) return x; var left:Boolean = x