CurvePath.js 5.8 KB

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