CurvePath.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /**
  2. * @author zz85 / http://www.lab4games.net/zz85/blog
  3. *
  4. **/
  5. /**************************************************************
  6. * Curved Path - a curve path is simply a array of connected
  7. * curves, but retains the api of a curve
  8. **************************************************************/
  9. THREE.CurvePath = function () {
  10. this.curves = [];
  11. this.bends = [];
  12. this.autoClose = false; // Automatically closes the path
  13. };
  14. THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
  15. THREE.CurvePath.prototype.add = function ( curve ) {
  16. this.curves.push( curve );
  17. };
  18. THREE.CurvePath.prototype.checkConnection = function() {
  19. // TODO
  20. // If the ending of curve is not connected to the starting
  21. // or the next curve, then, this is not a real path
  22. };
  23. THREE.CurvePath.prototype.closePath = function() {
  24. // TODO Test
  25. // and verify for vector3 (needs to implement equals)
  26. // Add a line curve if start and end of lines are not connected
  27. var startPoint = this.curves[0].getPoint(0);
  28. var endPoint = this.curves[this.curves.length-1].getPoint(1);
  29. if (!startPoint.equals(endPoint)) {
  30. this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
  31. }
  32. };
  33. // To get accurate point with reference to
  34. // entire path distance at time t,
  35. // following has to be done:
  36. // 1. Length of each sub path have to be known
  37. // 2. Locate and identify type of curve
  38. // 3. Get t for the curve
  39. // 4. Return curve.getPointAt(t')
  40. THREE.CurvePath.prototype.getPoint = function( t ) {
  41. var d = t * this.getLength();
  42. var curveLengths = this.getCurveLengths();
  43. var i = 0, diff, curve;
  44. // To think about boundaries points.
  45. while ( i < curveLengths.length ) {
  46. if ( curveLengths[ i ] >= d ) {
  47. diff = curveLengths[ i ] - d;
  48. curve = this.curves[ i ];
  49. var u = 1 - diff / curve.getLength();
  50. return curve.getPointAt( u );
  51. break;
  52. }
  53. i ++;
  54. }
  55. return null;
  56. // loop where sum != 0, sum > d , sum+1 <d
  57. };
  58. /*
  59. THREE.CurvePath.prototype.getTangent = function( t ) {
  60. };*/
  61. // We cannot use the default THREE.Curve getPoint() with getLength() because in
  62. // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
  63. // getPoint() depends on getLength
  64. THREE.CurvePath.prototype.getLength = function() {
  65. var lens = this.getCurveLengths();
  66. return lens[ lens.length - 1 ];
  67. };
  68. // Compute lengths and cache them
  69. // We cannot overwrite getLengths() because UtoT mapping uses it.
  70. THREE.CurvePath.prototype.getCurveLengths = function() {
  71. // We use cache values if curves and cache array are same length
  72. if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
  73. return this.cacheLengths;
  74. };
  75. // Get length of subsurve
  76. // Push sums into cached array
  77. var lengths = [], sums = 0;
  78. var i, il = this.curves.length;
  79. for ( i = 0; i < il; i ++ ) {
  80. sums += this.curves[ i ].getLength();
  81. lengths.push( sums );
  82. }
  83. this.cacheLengths = lengths;
  84. return lengths;
  85. };
  86. // Returns min and max coordinates, as well as centroid
  87. THREE.CurvePath.prototype.getBoundingBox = function () {
  88. var points = this.getPoints();
  89. var maxX, maxY;
  90. var minX, minY;
  91. maxX = maxY = Number.NEGATIVE_INFINITY;
  92. minX = minY = Number.POSITIVE_INFINITY;
  93. var p, i, il, sum;
  94. sum = new THREE.Vector2();
  95. for ( i = 0, il = points.length; i < il; i ++ ) {
  96. p = points[ i ];
  97. if ( p.x > maxX ) maxX = p.x;
  98. else if ( p.x < minX ) minX = p.x;
  99. if ( p.y > maxY ) maxY = p.y;
  100. else if ( p.y < minY ) minY = p.y;
  101. sum.addSelf( p.x, p.y );
  102. }
  103. return {
  104. minX: minX,
  105. minY: minY,
  106. maxX: maxX,
  107. maxY: maxY,
  108. centroid: sum.divideScalar( il )
  109. };
  110. };
  111. /**************************************************************
  112. * Create Geometries Helpers
  113. **************************************************************/
  114. /// Generate geometry from path points (for Line or ParticleSystem objects)
  115. THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
  116. var pts = this.getPoints( divisions, true );
  117. return this.createGeometry( pts );
  118. };
  119. // Generate geometry from equidistance sampling along the path
  120. THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
  121. var pts = this.getSpacedPoints( divisions, true );
  122. return this.createGeometry( pts );
  123. };
  124. THREE.CurvePath.prototype.createGeometry = function( points ) {
  125. var geometry = new THREE.Geometry();
  126. for ( var i = 0; i < points.length; i ++ ) {
  127. geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, 0 ) );
  128. }
  129. return geometry;
  130. };
  131. /**************************************************************
  132. * Bend / Wrap Helper Methods
  133. **************************************************************/
  134. // Wrap path / Bend modifiers?
  135. THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
  136. this.bends.push( bendpath );
  137. };
  138. THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
  139. var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
  140. var i, il;
  141. if ( !bends ) {
  142. bends = this.bends;
  143. }
  144. for ( i = 0, il = bends.length; i < il; i ++ ) {
  145. oldPts = this.getWrapPoints( oldPts, bends[ i ] );
  146. }
  147. return oldPts;
  148. };
  149. THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
  150. var oldPts = this.getSpacedPoints( segments );
  151. var i, il;
  152. if ( !bends ) {
  153. bends = this.bends;
  154. }
  155. for ( i = 0, il = bends.length; i < il; i ++ ) {
  156. oldPts = this.getWrapPoints( oldPts, bends[ i ] );
  157. }
  158. return oldPts;
  159. };
  160. // This returns getPoints() bend/wrapped around the contour of a path.
  161. // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
  162. THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
  163. var bounds = this.getBoundingBox();
  164. var i, il, p, oldX, oldY, xNorm;
  165. for ( i = 0, il = oldPts.length; i < il; i ++ ) {
  166. p = oldPts[ i ];
  167. oldX = p.x;
  168. oldY = p.y;
  169. xNorm = oldX / bounds.maxX;
  170. // If using actual distance, for length > path, requires line extrusions
  171. //xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
  172. xNorm = path.getUtoTmapping( xNorm, oldX );
  173. // check for out of bounds?
  174. var pathPt = path.getPoint( xNorm );
  175. var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
  176. p.x = pathPt.x + normal.x;
  177. p.y = pathPt.y + normal.y;
  178. }
  179. return oldPts;
  180. };
粤ICP备19079148号