PageRenderTime 41ms CodeModel.GetById 13ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/away3d/extrusions/utils/Path.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 304 lines | 159 code | 46 blank | 99 comment | 27 complexity | 3ab3f6c61800e83b2fe54e4dc7545ff3 MD5 | raw file
  1package away3d.extrusions.utils
  2{
  3	import flash.geom.Vector3D;
  4
  5	//import away3d.containers.Scene3D;
  6	//import away3d.extrusions.utils.PathDebug;
  7
  8	/**
  9	 * Holds information about a single Path definition.
 10	 * DEBUG OPTION OUT AT THIS TIME OF DEV
 11	 */
 12    public class Path
 13    {
 14		/**
 15		 * Creates a new <code>Path</code> object.
 16		 * 
 17		 * @param	 aVectors		[optional] An array of a series of Vector3D's organized in the following fashion. [a,b,c,a,b,c etc...] a = pEnd, b=pControl (control point), c = v2
 18		 */
 19		 
 20        public function Path(aVectors:Vector.<Vector3D> = null)
 21        {
 22			if(aVectors!= null && aVectors.length < 3)
 23				throw new Error("Path Vector.<Vector3D> must contain at least 3 Vector3D's");
 24			
 25            _segments = new Vector.<PathSegment>();
 26			
 27			if(aVectors != null)
 28				for(var i:int = 0; i<aVectors.length; i+=3)
 29					_segments.push( new PathSegment(aVectors[i], aVectors[i+1], aVectors[i+2]));
 30			 
 31        }
 32		
 33		 
 34		//private var _pathDebug:PathDebug;
 35		 
 36        private var _segments:Vector.<PathSegment>;
 37		
 38		/**
 39    	 * The worldAxis of reference
 40    	 */
 41		public var worldAxis:Vector3D = new Vector3D(0,1,0);
 42    	
 43		
 44        private var _smoothed:Boolean;
 45		/**
 46    	 * returns true if the smoothPath handler is being used.
 47    	 */
 48		public function get smoothed():Boolean
 49		{
 50			return _smoothed;
 51		}
 52		
 53		private var _averaged:Boolean;
 54		/**
 55    	* returns true if the averagePath handler is being used.
 56    	*/
 57		public function get averaged():Boolean
 58		{
 59			return _averaged;
 60		}
 61		
 62		/**
 63		 * display the path in scene
 64		 */
 65		/*public function debugPath(scene:Scene3D):void
 66        {
 67			_pathDebug = new PathDebug(scene, this);
 68        }*/
 69		/**
 70		 * Defines if the anchors must be displayed if debugPath has been called. if false, only curves are displayed
 71		 */
 72		/*public function get showAnchors():Boolean
 73        {
 74			if(!_pathDebug)
 75				throw new Error("Patheditor not set yet! Use Path.debugPath() method first");
 76				
 77			return _pathDebug.showAnchors;
 78		}
 79		public function set showAnchors(b:Boolean):void
 80        {
 81			if(!_pathDebug)
 82				throw new Error("Patheditor not set yet! Use Path.debugPath() method first");
 83			
 84			_pathDebug.showAnchors = b;
 85        }
 86		 */
 87		/**
 88		 * Defines if the path data must be visible or not if debugPath has been called
 89		 */
 90		 /*
 91		public function get display():Boolean
 92        {
 93			return _pathDebug.display;
 94		}
 95		public function set display(b:Boolean):void
 96        {
 97			if(!_pathDebug)
 98				throw new Error("Patheditor not set yet! Use Path.debugPath() method first");
 99			
100			_pathDebug.display = b;
101        }*/
102		
103		 
104		/**
105		 * adds a PathSegment to the path
106		 * @see PathSegment:
107		 */
108		public function add(ps:PathSegment):void
109        {
110			_segments.push(ps);
111        }
112		
113		/**
114		 * returns the length of the Path elements array
115		 * 
116		 * @return	an integer: the length of the Path elements array
117		 */
118		public function get length():int
119        {
120			return _segments.length;
121        }
122		
123		/**
124		 * returns the Vector.&lt;PathSegment&gt; holding the elements (PathSegment) of the path
125		 * 
126		 * @return	a Vector.&lt;PathSegment&gt;: holding the elements (PathSegment) of the path
127		 */
128		public function get segments():Vector.<PathSegment>
129        {
130			return _segments;
131        }
132		
133		/**
134		 * returns a given PathSegment from the path (PathSegment holds 3 Vector3D's)
135		 * 
136		 * @param	 indice uint. the indice of a given PathSegment		
137		 * @return	given PathSegment from the path
138		 */
139		public function getSegmentAt(indice:uint):PathSegment
140        {
141			return _segments[indice];
142        }
143        
144		/**
145		 * removes a segment in the path according to id.
146		 *
147		 * @param	 index	int. The index in path of the to be removed curvesegment 
148		 * @param	 join 		Boolean. If true previous and next segments coordinates are reconnected
149		 */
150		public function removeSegment(index:int, join:Boolean = false):void
151        {
152			if(_segments.length == 0 || _segments[index ] == null )
153				return;
154			
155			if(join && index < _segments.length-1 && index>0){
156				var seg:PathSegment = _segments[index];
157				var prevSeg:PathSegment = _segments[index-1];
158				var nextSeg:PathSegment = _segments[index+1];
159				prevSeg.pControl.x = (prevSeg.pControl.x+seg.pControl.x)*.5;
160				prevSeg.pControl.y = (prevSeg.pControl.y+seg.pControl.y)*.5;
161				prevSeg.pControl.z = (prevSeg.pControl.z+seg.pControl.z)*.5;
162				nextSeg.pControl.x = (nextSeg.pControl.x+seg.pControl.x)*.5;
163				nextSeg.pControl.y = (nextSeg.pControl.y+seg.pControl.y)*.5;
164				nextSeg.pControl.z = (nextSeg.pControl.z+seg.pControl.z)*.5;
165				prevSeg.pEnd.x = (seg.pStart.x + seg.pEnd.x)*.5;
166				prevSeg.pEnd.y = (seg.pStart.y + seg.pEnd.y)*.5;
167				prevSeg.pEnd.z = (seg.pStart.z + seg.pEnd.z)*.5;
168				nextSeg.pStart.x = prevSeg.pEnd.x;
169				nextSeg.pStart.y = prevSeg.pEnd.y;
170				nextSeg.pStart.z = prevSeg.pEnd.z;
171				
172				/*if(_pathDebug != null)
173					_pathDebug.updateAnchorAt(index-1);
174					_pathDebug.updateAnchorAt(index+1);*/
175			}
176			
177			if(_segments.length > 1){
178				_segments.splice(index, 1);
179			} else{
180				_segments = new Vector.<PathSegment>();
181			}
182        }
183		
184		/**
185		 * handler will smooth the path using anchors as control vector of the PathSegments 
186		 * note that this is not dynamic, the PathSegments values are overwrited
187		 */
188		public function smoothPath():void
189        {
190			if(_segments.length <= 2)
191				return;
192			 
193			_smoothed = true;
194			_averaged = false;
195			 
196			var x:Number;
197			var y:Number;
198			var z:Number;
199			var seg0:Vector3D;
200			var seg1:Vector3D;
201			var tmp:Vector.<Vector3D> = new Vector.<Vector3D>();
202			var i:uint;
203			
204			var startseg:Vector3D = new Vector3D(_segments[0].pStart.x, _segments[0].pStart.y, _segments[0].pStart.z);
205			var endseg:Vector3D = new Vector3D(_segments[_segments.length-1].pEnd.x, 
206																		_segments[_segments.length-1].pEnd.y,
207																		_segments[_segments.length-1].pEnd.z);
208			for(i = 0; i< length-1; ++i)
209			{
210				if(_segments[i].pControl == null)
211					_segments[i].pControl = _segments[i].pEnd;
212				
213				if(_segments[i+1].pControl == null)
214					_segments[i+1].pControl = _segments[i+1].pEnd;
215				
216				seg0 = _segments[i].pControl;
217				seg1 = _segments[i+1].pControl;
218				x = (seg0.x + seg1.x) * .5;
219				y = (seg0.y + seg1.y) * .5;
220				z = (seg0.z + seg1.z) * .5;
221				
222				tmp.push( startseg,  new Vector3D(seg0.x, seg0.y, seg0.z), new Vector3D(x, y, z));
223				startseg = new Vector3D(x, y, z);
224				_segments[i] = null;
225			}
226			
227			seg0 = _segments[_segments.length-1].pControl;
228			tmp.push( startseg,  new Vector3D((seg0.x+seg1.x)*.5, (seg0.y+seg1.y)*.5, (seg0.z+seg1.z)*.5), endseg);
229			
230			_segments = new Vector.<PathSegment>();
231			
232			for(i = 0; i<tmp.length; i+=3)
233				_segments.push( new PathSegment(tmp[i], tmp[i+1], tmp[i+2]) );
234				tmp[i] = tmp[i+1] = tmp[i+2] = null;
235			 
236			tmp = null;
237		}
238		
239		/**
240		 * handler will average the path using averages of the PathSegments
241		 * note that this is not dynamic, the path values are overwrited
242		 */
243		public function averagePath():void
244        {
245			_averaged = true;
246			_smoothed = false;
247			
248			for(var i:uint = 0; i<_segments.length; ++i){
249				_segments[i].pControl.x = (_segments[i].pStart.x+_segments[i].pEnd.x)*.5;
250				_segments[i].pControl.y = (_segments[i].pStart.y+_segments[i].pEnd.y)*.5;
251				_segments[i].pControl.z = (_segments[i].pStart.z+_segments[i].pEnd.z)*.5;
252			}
253        }
254        
255  		public function continuousCurve(points:Vector.<Vector3D>, closed:Boolean = false):void
256  		{
257  			var aVectors:Vector.<Vector3D> = new Vector.<Vector3D>();
258  			var i:uint;
259  			var X:Number;
260			var Y:Number;
261			var Z:Number;
262			var midPoint:Vector3D;
263			
264  			// Find the mid points and inject them into the array.
265  			for(i = 0; i < points.length - 1; i++)
266  			{
267  				var currentPoint:Vector3D = points[i];
268  				var nextPoint:Vector3D = points[i+1];
269  				
270  				X = (currentPoint.x + nextPoint.x)/2;
271  				Y = (currentPoint.y + nextPoint.y)/2;
272  				Z = (currentPoint.z + nextPoint.z)/2;
273  				midPoint = new Vector3D(X, Y, Z);
274  				
275  				if (i) aVectors.push(midPoint);
276  				
277  				if (i < points.length - 2 || closed) {
278	  				aVectors.push(midPoint);
279	  				aVectors.push(nextPoint);
280  				}
281  			}
282  			
283  			if(closed) {
284	  			currentPoint = points[points.length-1];
285	  			nextPoint = points[0];
286	  			X = (currentPoint.x + nextPoint.x)/2;
287  				Y = (currentPoint.y + nextPoint.y)/2;
288  				Z = (currentPoint.z + nextPoint.z)/2;
289  				midPoint = new Vector3D(X, Y, Z);
290  				
291  				aVectors.push(midPoint);
292  				aVectors.push(midPoint);
293  				aVectors.push(points[0]);
294  				aVectors.push(aVectors[0]);
295	  		}
296	  		
297            _segments = new Vector.<PathSegment>();
298			
299			for(i = 0; i< aVectors.length; i+=3)
300				_segments.push( new PathSegment(aVectors[i], aVectors[i+1], aVectors[i+2]));
301  		}
302		
303    }
304}