/sandy/as2/branches/2_0/sandy/core/data/BezierPath.as

http://sandy.googlecode.com/ · ActionScript · 199 lines · 92 code · 20 blank · 87 comment · 10 complexity · abcd6372f1237fcaf10d5cfcad36c404 MD5 · raw file

  1. /*
  2. # ***** BEGIN LICENSE BLOCK *****
  3. Copyright the original author or authors.
  4. Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.mozilla.org/MPL/MPL-1.1.html
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. # ***** END LICENSE BLOCK *****
  14. */
  15. import sandy.core.data.Vector;
  16. import sandy.util.BezierUtil;
  17. /**
  18. * A 3D path interpolated with Bezier equations
  19. *
  20. * <p>A Bezier path is basically an array of 3D points, but the path is interpolated thanks to Bezier equations, allowing
  21. * some nice movements</p>
  22. *
  23. * @author Thomas Pfeiffer - kiroukou
  24. * @version 1.0
  25. * @date 27.04.2006
  26. */
  27. class sandy.core.data.BezierPath
  28. {
  29. /**
  30. * Create a new {@code BezierPath} Instance.
  31. */
  32. public function BezierPath( /*pbBoucle:Boolean*/ )
  33. {
  34. _aContainer = new Array();
  35. _aSegments = new Array();
  36. _nCrtSegment = 0;
  37. _bBoucle = false;
  38. _bCompiled = false;
  39. }
  40. /**
  41. * Returns the segment that fits to the percentage number passed in arguments.
  42. * You can imagine the whole path length as the 1.0 value (100%). Now if you need the segment when you are at only 10% of the whole path
  43. * you just have to pass 0.1 in argument, and the returned array contain the bezierCurve points [startPoint, controlPoint, endPoint]
  44. * @param pnId
  45. * @return Array array containing the segment's bezierCurve points [startPoint, controlPoint, endPoint]
  46. */
  47. public function getSegment( pnId:Number ):Array
  48. {
  49. if( pnId >= 0 && pnId < _nNbSegments )
  50. {
  51. return _aSegments[ int(pnId) ];
  52. }
  53. else
  54. {
  55. return null;
  56. }
  57. }
  58. /**
  59. * Returns the position in the 3D space at a specific percentage.
  60. * You can imagine the whole path length as the 1.0 value (100%). Now if you need the position when you are at only 10% of the whole path
  61. * you just have to pass 0.1 in argument, and the returned value is the position on that percentage of the whole path.
  62. * @param p Number A percentage between [0-1]
  63. * @return Vector The 3D position on the path at the current percentage.
  64. */
  65. public function getPosition( p:Number ):Vector
  66. {
  67. var id:Number = Math.floor(p/_nRatio);
  68. if( id == _nNbSegments )
  69. {
  70. id --;
  71. p = 1.0;
  72. }
  73. var seg:Array = getSegment( id );
  74. return BezierUtil.getPointsOnQuadCurve( (p-id*_nRatio)/_nRatio, seg[0], seg[1], seg[2] );
  75. }
  76. /**
  77. * Add a point to the path.
  78. * WARNING : You can't add a point to the path once it has been compiled.
  79. * @param x Number
  80. * @param y Number
  81. * @param z Number
  82. * @return Boolean true if operation succeed, false otherwise.
  83. */
  84. public function addPoint( x:Number, y:Number, z:Number ):Boolean
  85. {
  86. if( _bCompiled )
  87. {
  88. return false;
  89. }
  90. else
  91. {
  92. _aContainer.push( new Vector( x, y, z ) );
  93. return true;
  94. }
  95. }
  96. /**
  97. * Computes all the control points.
  98. * Must be called before being used by Sandy's engine. Should be called once tha last point of the path has been added.
  99. * @param void
  100. */
  101. public function compile(Void):Void
  102. {
  103. _nNbPoints = _aContainer.length;
  104. if( _nNbPoints >= 3 && _nNbPoints%2 == 0 )
  105. {
  106. trace('sandy.core.data.BezierPath ERROR: Number of points incompatible');
  107. return;
  108. }
  109. _bCompiled = true;
  110. _nNbSegments = 0;
  111. var a:Vector, b:Vector, c:Vector;
  112. for (var i:Number = 0; i <= _nNbPoints-2; i+=2 )
  113. {
  114. a = _aContainer[int(i)];
  115. b = _aContainer[int(i+1)];
  116. c = _aContainer[int(i+2)];
  117. _aSegments.push( [ a, b, c ] );
  118. }
  119. if( _bBoucle )
  120. {
  121. _aSegments.push([
  122. _aContainer[ int(_nNbPoints) ],
  123. BezierUtil.getQuadControlPoints(_aContainer[ int(_nNbPoints) ],_aContainer[ 0 ],_aContainer[ 1 ]),
  124. _aContainer[ 0 ]
  125. ]);
  126. }
  127. // --
  128. _nNbSegments = _aSegments.length;
  129. _nRatio = 1 / _nNbSegments;
  130. }
  131. /**
  132. * returns the number of segments;
  133. * @param void
  134. * @return Number the number of segments
  135. */
  136. public function getNumberOfSegments():Number
  137. {
  138. return _nNbSegments;
  139. }
  140. /**
  141. * Get a String represntation of the {@code BezierPath}.
  142. *
  143. * @return A String representing the {@code BezierPath}.
  144. */
  145. public function toString():String
  146. {
  147. return "sandy.core.data.BezierPath";
  148. }
  149. /**
  150. * properties used to store transformed coordinates in the local frame of the object
  151. */
  152. private var _aContainer:Array;
  153. /**
  154. * Array of segments
  155. */
  156. private var _aSegments:Array;
  157. /**
  158. * current segment id
  159. */
  160. private var _nCrtSegment:Number;
  161. /**
  162. * The number of segments of the path
  163. */
  164. private var _nNbSegments:Number;
  165. /**
  166. * The number of points of the path
  167. */
  168. private var _nNbPoints:Number;
  169. /**
  170. * Boolean set to true is the path has to be closed, false otherwise. default is false
  171. */
  172. private var _bBoucle:Boolean;
  173. /**
  174. * Boolean keeping the state the the path, compiled or not
  175. */
  176. private var _bCompiled:Boolean;
  177. private var _nRatio:Number;
  178. }