diff --git a/src/extras/geometries/Curve.js b/src/extras/geometries/Curve.js index f9d45d86..106cf252 100644 --- a/src/extras/geometries/Curve.js +++ b/src/extras/geometries/Curve.js @@ -91,17 +91,19 @@ THREE.Curve.prototype.getLength = function () { THREE.Curve.prototype.getLengths = function ( divisions ) { if ( !divisions ) divisions = 200; - - if ( this.cacheLengths && ( this.cacheLengths.length == divisions ) ) { + + if ( this.cacheLengths && ( this.cacheLengths.length == divisions + 1 ) ) { //console.log( "cached", this.cacheLengths ); return this.cacheLengths; } - + var cache = []; var current, last = this.getPoint( 0 ); var p, sum = 0; + + cache.push(0); for ( p = 1; p <= divisions; p++ ) { @@ -113,42 +115,89 @@ THREE.Curve.prototype.getLengths = function ( divisions ) { } this.cacheLengths = cache; + return cache; // { sums: cache, sum:sum }; Sum is in the last element. }; // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance - THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) { - var lengths = this.getLengths(); - var i = 0, il = lengths.length; + var arcLengths = this.getLengths(); + var i = 0, il = arcLengths.length; - var distanceForU; + var targetArcLength; // The targetted u distance value to get if ( distance ) { - distanceForU = distance; + targetArcLength = distance; } else { - distanceForU = u * lengths[ il - 1 ]; + targetArcLength = u * arcLengths[ il - 1 ]; } - // TODO Should do binary search + sub division + interpolation when needed + // // TODO Should do binary search + sub division + interpolation when needed + // time = Date.now(); + // while ( i < il ) { + // + // i++; + // + // if ( targetArcLength < arcLengths[ i ] ) break; + // + // } + // + // i--; + // console.log('o' , i, Date.now()- time); + + time = Date.now(); + // binary search for the index with largest value smaller than target u distance + var low=0, high = il-1, comparison; - while ( i < il ) { - - if ( lengths[ i ] > distanceForU ) break; - - i++; + while (low <= high) { + i = Math.floor((low + high) / 2); + comparison = arcLengths[ i ] - targetArcLength; + + if (comparison < 0) { + low = i + 1; continue; + } else if (comparison > 0) { + high = i - 1; continue; + } else { + high = i; + break; + // DONE + } + } + + i = high; + + //console.log('b' , i, low, high, Date.now()- time); + + + if (arcLengths[i] == targetArcLength) { + var t = i / (il - 1); + return t; + } + + // We could get finer grain ar lengths, or use simple interpolatation between two points + var lengthBefore = arcLengths[i]; + var lengthAfter = arcLengths[i+1]; + var segmentLength = lengthAfter - lengthBefore; + + // determine where we are between the 'before' and 'after' points. + var segmentFraction = (targetArcLength - lengthBefore) / segmentLength; + + // add that fractional amount to t + t = (i + segmentFraction) / (il -1); - var t = i / il; return t; - + + + + }; @@ -181,6 +230,14 @@ THREE.LineCurve.prototype.getPoint = function ( t ) { }; +THREE.LineCurve.prototype.getNormalVector = function( t ) { + tx = this.x2 - this.x1; + ty = this.y2 - this.y1; + + // return normal unit vector + return new THREE.Vector2( -ty , tx ).unit(); +} + /************************************************************** * Quadratic Bezier curve **************************************************************/ @@ -223,14 +280,14 @@ THREE.QuadraticBezierCurve.prototype.getNormalVector = function( t ) { var x0, y0, x1, y1, x2, y2; - x0 = this.actions[ 0 ].args[ 0 ]; - y0 = this.actions[ 0 ].args[ 1 ]; - - x1 = this.actions[ 1 ].args[ 0 ]; - y1 = this.actions[ 1 ].args[ 1 ]; - - x2 = this.actions[ 1 ].args[ 2 ]; - y2 = this.actions[ 1 ].args[ 3 ]; + // x0 = this.actions[ 0 ].args[ 0 ]; + // y0 = this.actions[ 0 ].args[ 1 ]; + // + // x1 = this.actions[ 1 ].args[ 0 ]; + // y1 = this.actions[ 1 ].args[ 1 ]; + // + // x2 = this.actions[ 1 ].args[ 2 ]; + // y2 = this.actions[ 1 ].args[ 3 ]; var tx, ty; diff --git a/src/extras/geometries/ExtrudeGeometry.js b/src/extras/geometries/ExtrudeGeometry.js index 78b0e939..c7cf1160 100644 --- a/src/extras/geometries/ExtrudeGeometry.js +++ b/src/extras/geometries/ExtrudeGeometry.js @@ -63,6 +63,8 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) { var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; var steps = options.steps !== undefined ? options.steps : 1; + + var bendPath = options.bendPath; var extrudePath = options.path !== undefined ? options.path : null; var extrudePts, extrudeByPath = false; @@ -98,7 +100,9 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) { var shapesOffset = this.vertices.length; var shapePoints = shape.extractAllPoints( curveSegments ); // use shape.extractAllSpacedPoints( curveSegments ) for points with equal divisions + shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath ); + var vertices = shapePoints.shape; var holes = shapePoints.holes; @@ -129,7 +133,11 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) { var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes ); //var faces = THREE.Shape.Utils.triangulate2( vertices, holes ); - + + // shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath ); + // vertices = shapePoints.shape; + // holes = shapePoints.holes; + //console.log(faces); //// diff --git a/src/extras/geometries/Path.js b/src/extras/geometries/Path.js index 30da7236..f282bb96 100644 --- a/src/extras/geometries/Path.js +++ b/src/extras/geometries/Path.js @@ -517,16 +517,28 @@ THREE.Path.prototype.createGeometry = function( points ) { // FUTURE refactor path = an array of lines -> straight, bezier, splines, arc, funcexpr lines // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html -THREE.Path.prototype.transform = function( path ) { +// This returns getPoints() bend/wrapped around the contour of a path. - path = new THREE.Path(); - path.moveTo( 0, 0 ); - path.quadraticCurveTo( 100, 20, 140, 80 ); +THREE.Path.prototype.transform = function( path, segments ) { - console.log( path.cacheArcLengths() ); + var bounds = this.getBoundingBox(); + var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints + + // path = new THREE.Path(); + // path.moveTo( 0, 0 ); + // path.quadraticCurveTo( 100, 20, 140, 80 ); + + path = new THREE.QuadraticBezierCurve( 0, 0, 150, 100, 400, 0) + //path = new THREE.QuadraticBezierCurve( 0, 0, bounds.maxX/2, 50, bounds.maxX , 0); + + //path = new THREE.LineCurve( 0, 0, 400, 0); + - var thisBounds = this.getBoundingBox(); - var oldPts = this.getPoints(); + //console.log( path.cacheArcLengths() ); + //path.getLengths(400); + //segments = 40; + + var i, il, p, oldX, oldY, xNorm; @@ -537,19 +549,19 @@ THREE.Path.prototype.transform = function( path ) { oldX = p.x; oldY = p.y; - var xNorm = oldX/ thisBounds.maxX; + var xNorm = oldX/ bounds.maxX; // If using actual distance, for length > path, requires line extrusions //xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance + xNorm = path.getUtoTmapping(xNorm, oldX ); + var pathPt = path.getPoint( xNorm ); var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY ); p.x = pathPt.x + normal.x; p.y = pathPt.y + normal.y; - //p.x = a * oldX + b * oldY + c; - //p.y = d * oldY + e * oldX + f; } diff --git a/src/extras/geometries/Shape.js b/src/extras/geometries/Shape.js index c3701370..4cb6e135 100644 --- a/src/extras/geometries/Shape.js +++ b/src/extras/geometries/Shape.js @@ -30,14 +30,23 @@ THREE.Shape.prototype.extrude = function ( options ) { // Get points of holes -THREE.Shape.prototype.getPointsHoles = function ( divisions ) { +THREE.Shape.prototype.getPointsHoles = function ( divisions, bend ) { var i, il = this.holes.length, holesPts = []; for ( i = 0; i < il; i ++ ) { - holesPts[ i ] = this.holes[ i ].getPoints( divisions ); + if (bend) { + + holesPts[ i ] = this.holes[ i ].transform( bend, divisions ); + + } else { + + holesPts[ i ] = this.holes[ i ].getPoints( divisions ); + + } + } @@ -75,6 +84,17 @@ THREE.Shape.prototype.extractAllPoints = function ( divisions ) { }; +THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) { + + return { + + shape: this.transform( bend, divisions ), + holes: this.getPointsHoles( divisions, bend ) + + }; + +}; + // Get points of shape and holes (spaced by regular distance) THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) { @@ -131,16 +151,13 @@ THREE.Shape.Utils = { shortest = Number.POSITIVE_INFINITY; - // THIS THING NEEDS TO BE DONE CORRECTLY AGAIN :( - + // Find the shortest pair of pts between shape and hole // Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n) // Using distanceToSquared() intead of distanceTo() should speed a little // since running square roots operations are reduced. - // http://en.wikipedia.org/wiki/Closest_pair_of_points - // http://stackoverflow.com/questions/1602164/shortest-distance-between-points-algorithm - + for ( h2 = 0; h2 < hole.length; h2 ++ ) { pts1 = hole[ h2 ]; @@ -276,7 +293,6 @@ THREE.Shape.Utils = { verts.push( triangleb ); shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 ); - //shape = tmpHole1.concat( tmpHole2 ); } diff --git a/src/extras/geometries/TextGeometry.js b/src/extras/geometries/TextGeometry.js index 628ad14a..4d66555c 100644 --- a/src/extras/geometries/TextGeometry.js +++ b/src/extras/geometries/TextGeometry.js @@ -49,6 +49,13 @@ THREE.TextGeometry = function ( text, parameters ) { if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10; if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8; if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false; + + + var bend = new THREE.Path(); + bend.moveTo(0,0); + bend.quadraticCurveTo( 500, 100, 1000, 0 ); + + parameters.bendPath = bend; THREE.ExtrudeGeometry.call( this, textShapes, parameters );