|
| 1 | +package as3geometry.geom2D.ui.ParabolaDrawer |
| 2 | +{ |
| 3 | +import as3geometry.AS3GeometryContext; |
| 4 | +import as3geometry.geom2D.Line; |
| 5 | +import as3geometry.geom2D.Parabola; |
| 6 | +import as3geometry.geom2D.Vertex; |
| 7 | +import as3geometry.geom2D.ui.generic.UIDrawer; |
| 8 | +import as3geometry.geom2D.util.ParabolaHelper; |
| 9 | + |
| 10 | +import ui.Paint; |
| 11 | + |
| 12 | +import flash.events.Event; |
| 13 | + |
| 14 | +public class ParabolaDrawer extends UIDrawer |
| 15 | +{ |
| 16 | + |
| 17 | +private var _parabola:Parabola; |
| 18 | + |
| 19 | +private var _diagonal:Number; |
| 20 | + |
| 21 | +private var _drawPending:Boolean; |
| 22 | + |
| 23 | +private var _helper:ParabolaHelper; |
| 24 | + |
| 25 | +public function ParabolaDrawer(context:AS3GeometryContext, parabola:Parabola, paint:Paint = null) |
| 26 | +{ |
| 27 | +super(context, paint); |
| 28 | +addDefinien(_parabola = parabola); |
| 29 | + |
| 30 | +_drawPending = false; |
| 31 | +_helper = new ParabolaHelper(); |
| 32 | + |
| 33 | +addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); |
| 34 | +} |
| 35 | + |
| 36 | +private function onAddedToStage(event:Event):void |
| 37 | +{ |
| 38 | +removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); |
| 39 | +_diagonal = calculateDiagonal(); |
| 40 | + |
| 41 | +if (_drawPending) |
| 42 | +draw(); |
| 43 | +} |
| 44 | + |
| 45 | +private function calculateDiagonal():Number |
| 46 | +{ |
| 47 | +var w:int = stage.stageWidth; |
| 48 | +var h:int = stage.stageHeight; |
| 49 | + |
| 50 | +return Math.sqrt(w * w + h * h); |
| 51 | +} |
| 52 | + |
| 53 | +public function get parabola():Parabola |
| 54 | +{ |
| 55 | +return _parabola; |
| 56 | +} |
| 57 | + |
| 58 | +public function set parabola(value:Parabola):void |
| 59 | +{ |
| 60 | +if (_parabola == value) |
| 61 | +return; |
| 62 | + |
| 63 | +removeDefinien(_parabola); |
| 64 | +addDefinien(_parabola = value); |
| 65 | +invalidate(); |
| 66 | +} |
| 67 | + |
| 68 | +override protected function draw():void |
| 69 | +{ |
| 70 | +if (!stage) |
| 71 | +{ |
| 72 | +_drawPending = true; |
| 73 | +return; |
| 74 | +} |
| 75 | + |
| 76 | +_drawPending = false; |
| 77 | + |
| 78 | +var line:Line = _parabola.directrix; |
| 79 | + |
| 80 | +// the line registration point a |
| 81 | +var a:Vertex = line.a; |
| 82 | +var ax:Number = a.x; |
| 83 | +var ay:Number = a.y; |
| 84 | + |
| 85 | +// the line registraion point b |
| 86 | +var b:Vertex = line.b; |
| 87 | +var bx:Number = b.x; |
| 88 | +var by:Number = b.y; |
| 89 | + |
| 90 | +// the parabola focus |
| 91 | +var c:Vertex = _parabola.focus; |
| 92 | +var cx:Number = c.x; |
| 93 | +var cy:Number = c.y; |
| 94 | + |
| 95 | +// the vector from a to be that defines the direction of the line |
| 96 | +var bx_ax:Number = bx - ax; |
| 97 | +var by_ay:Number = by - ay; |
| 98 | +var abSqrd:Number = (bx_ax * bx_ax + by_ay * by_ay); |
| 99 | +var abInv:Number = 1 / Math.sqrt(abSqrd); |
| 100 | + |
| 101 | +// we want to get the vector from c to the point closest to it on the |
| 102 | +// line ab. Call that point d. We know that the vector cd is perpendicular |
| 103 | +// to the vector ab. delta is the amount we have to scale the vector ab to |
| 104 | +// get the right length for cd. |
| 105 | +var cx_ax:Number = cx - ax; |
| 106 | +var cy_ay:Number = cy - ay; |
| 107 | +var delta:Number = (by_ay * cx_ax - bx_ax * cy_ay) / abSqrd; |
| 108 | + |
| 109 | +// the vector cd defined |
| 110 | +var dx_cx:Number = -by_ay * delta; |
| 111 | +var dy_cy:Number = bx_ax * delta; |
| 112 | + |
| 113 | +// the point d defined, along with the length of cd. This is the 'focal |
| 114 | +// parameter' of the parabola, which is an important value. |
| 115 | +var dx:Number = cx + dx_cx; |
| 116 | +var dy:Number = cy + dy_cy; |
| 117 | +var cd:Number = Math.sqrt(dx_cx * dx_cx + dy_cy * dy_cy); |
| 118 | +var cdInv:Number = 1 / cd; |
| 119 | +var cdHalf:Number = cd * 0.5; |
| 120 | + |
| 121 | +// the point e defined, which lies between the focus and directrix |
| 122 | +// where the parametric value is 0 (the closest point to both the focus |
| 123 | +// and directrix) |
| 124 | +var ex:Number = cx + dx_cx * 0.5; |
| 125 | +var ey:Number = cy + dy_cy * 0.5; |
| 126 | + |
| 127 | +// the strategy now is to use the parametric form of the parabola equation |
| 128 | +// to work out where if you project a and b onto the parabola, they would |
| 129 | +// be positioned. To do this I need to tranlsate the coordinate system of |
| 130 | +// the parameteric equations into the real coordinate sytem... |
| 131 | + |
| 132 | +// (mx,my) is a unit vector along the line ab, which will be my x-vector. |
| 133 | +// my y-vector will be it's perpendicular: (-my,mx) |
| 134 | +var mx:Number = bx_ax * abInv; |
| 135 | +var my:Number = by_ay * abInv; |
| 136 | + |
| 137 | +// work out how far a is away from d anormx, which in the normal parametric |
| 138 | +// form is my x coordinate. This lets me derive the parameter |
| 139 | +// T which lets me derive the normal parametric coordinate anormy. |
| 140 | +var dx_ax:Number = dx - ax; |
| 141 | +var dy_ay:Number = dy - ay; |
| 142 | +var anormx:Number = -Math.sqrt(dx_ax * dx_ax + dy_ay * dy_ay); |
| 143 | +var aT:Number = anormx * cdInv; |
| 144 | +var anormy:Number = cdHalf * aT * aT; |
| 145 | + |
| 146 | +// do the same thing as just described for b as well |
| 147 | +var dx_bx:Number = dx - bx; |
| 148 | +var dy_by:Number = dy - by; |
| 149 | +var bnormx:Number = Math.sqrt(dx_bx * dx_bx + dy_by * dy_by); |
| 150 | +var bT:Number = bnormx * cdInv; |
| 151 | +var bnormy:Number = cdHalf * bT * bT; |
| 152 | + |
| 153 | +// now convert that into real-world coordinates by translating (dx,dy) |
| 154 | +// along the axes (mx,my) and (-my,mx) by the magnitudes [amx,amy] and |
| 155 | +// [bmx,bmy]. |
| 156 | +var fx:Number = ex + anormx * mx - anormy * my; |
| 157 | +var fy:Number = ey + anormx * my + anormy * mx; |
| 158 | +var tx:Number = ex + bnormx * mx - bnormy * my; |
| 159 | +var ty:Number = ey + bnormx * my + bnormy * mx; |
| 160 | + |
| 161 | +graphics.moveTo(fx, fy); |
| 162 | +graphics.curveTo(dx, dy, tx, ty); |
| 163 | + |
| 164 | +} |
| 165 | + |
| 166 | + |
| 167 | + |
| 168 | +} |
| 169 | +} |
0 commit comments