<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:degrafa="http://www.degrafa.com/2007" xmlns:geom="components.*" xmlns="http://www.degrafa.com/2007" layout="absolute" width="600" height="500" pageTitle="Degrafa Advanced Cubic Bezier" viewSourceURL="srcview/index.html" applicationComplete="test()" > <mx:Style source="assets/style/style.css"/> <mx:Canvas id="background" x="50" y="90" width="500" height="360" backgroundColor="#FFFFFF" > <mx:Label x="10" y="300" text="Left stepper modifies t1, right modifies t2 or move interpolation points for new refinement." width="480" color="#000000" fontSize="12"/> </mx:Canvas> <mx:Label text="Quad Bezier Refinement" x="250" y="30" width="300" styleName="title"/> <mx:Canvas id="bezierLayer" /> <geom:InteractivePoint id="P0" x="90" y="250" pointLabel="P0" radius="5" color="0x00ff00" width="100" height="20" /> <geom:InteractivePoint id="P1" x="150" y="150" pointLabel="P1" radius="5" color="0x00ff00" width="100" height="20" /> <geom:InteractivePoint id="P2" x="290" y="200" pointLabel="P2" radius="5" color="0x00ff00" width="100" height="20" /> <mx:NumericStepper x="418" y="418" id="__t1__" stepSize="0.1" minimum="0.1" maximum="0.8" change="onT1Changed()"/> <mx:NumericStepper x="487" y="418" id="__t2__" minimum="0.2" maximum="0.9" stepSize="0.1" change="onT2Changed()"/> <AdvancedQuadraticBezier id="bezier" graphicsTarget="{[bezierLayer]}"> <stroke> <SolidStroke weight="2" color="#0000FF"/> </stroke> </AdvancedQuadraticBezier> <mx:Script> <![CDATA[ import mx.events.PropertyChangeEvent; import mx.core.UIComponent; import com.degrafa.GraphicPointEX; import com.degrafa.core.collections.GraphicPointCollection; import com.degrafa.geometry.utilities.BezierUtils; // refinement bounds must be in open interval (0,1) private var __t1:Number = 0.2; private var __t2:Number = 0.6; private var __refinement:UIComponent = new UIComponent(); private function test():void { // restrict dragging for each point var bounds:Rectangle = new Rectangle(background.x, background.y, background.width, background.height); P0.restrict = bounds; P1.restrict = bounds; P2.restrict = bounds; // actions when a property is changed on any InteractivePoint P0.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onPropertyChanged); P1.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onPropertyChanged); P2.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onPropertyChanged); __t1__.value = __t1; __t2__.value = __t2; // assign the bezier data from script - the quad interpolates the three points and show initial refinement in [t1,t2] assignBezierInterpolationPoints(); refineQuad(); // arghh .... addChild(__refinement); } private function set t1(t:Number):void { if( t != __t1 && t < __t2 && t > 0 ) __t1 = t; } private function set t2(t:Number):void { if( t != __t2 && t > __t1 && t < 1 ) __t2 = t; } private function assignBezierInterpolationPoints():void { // property changes trigger redraw var t:Number = bezier.interpolate( [new Point(P0.x, P0.y), new Point(P1.x, P1.y), new Point(P2.x, P2.y)] ); } private function onPropertyChanged(_e:PropertyChangeEvent):void { switch( _e.property ) { case InteractivePoint.MOUSE_DOWN: var g:Graphics = __refinement.graphics; g.clear(); addEventListener(Event.ENTER_FRAME, onPointMove); break; case InteractivePoint.MOUSE_UP: removeEventListener(Event.ENTER_FRAME, onPointMove); // refine at [t1,t2] refineQuad(); break; } } // redraw control points and bezier curve when an InteractivePoint is moved private function onPointMove(_e:Event):void { assignBezierInterpolationPoints(); } // display refinement in [t1,t2] private function refineQuad():void { var g:Graphics = __refinement.graphics; g.clear(); g.lineStyle(2,0xff0000); var quad:Object = BezierUtils.quadRefine(bezier, __t1, __t2); g.moveTo(quad.x0, quad.y0); g.curveTo(quad.cx, quad.cy, quad.x1, quad.y1); } // note that t2 must be strictly greater than t1 private function onT1Changed():void { if( __t1__.value < __t2 ) { t1 = __t1__.value; refineQuad(); } else __t1__.value = __t1; } private function onT2Changed():void { if( __t2__.value > __t1 ) { t2 = __t2__.value; refineQuad(); } else __t2__.value = __t2; } ]]> </mx:Script> </mx:Application>