CurvePath.js 4.8 KB
Newer Older
R
Rich Harris 已提交
1 2 3 4 5
import { Curve } from './Curve';
import { Vector3 } from '../../math/Vector3';
import { Geometry } from '../../core/Geometry';
import { LineCurve } from '../curves/LineCurve';

6 7
/**
 * @author zz85 / http://www.lab4games.net/zz85/blog
8
 *
9 10 11 12 13 14 15
 **/

/**************************************************************
 *	Curved Path - a curve path is simply a array of connected
 *  curves, but retains the api of a curve
 **************************************************************/

M
Mr.doob 已提交
16
function CurvePath() {
17

18
	this.curves = [];
F
Fabian Lange 已提交
19

Z
zz85 已提交
20
	this.autoClose = false; // Automatically closes the path
G
gero3 已提交
21

M
Mr.doob 已提交
22
}
23

R
Rich Harris 已提交
24
CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
25

R
Rich Harris 已提交
26
	constructor: CurvePath,
27

28
	add: function ( curve ) {
29

30
		this.curves.push( curve );
31

32
	},
G
gero3 已提交
33

34
	closePath: function () {
G
gero3 已提交
35

36 37 38
		// Add a line curve if start and end of lines are not connected
		var startPoint = this.curves[ 0 ].getPoint( 0 );
		var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
G
gero3 已提交
39

40
		if ( ! startPoint.equals( endPoint ) ) {
F
Fabian Lange 已提交
41

R
Rich Harris 已提交
42
			this.curves.push( new LineCurve( endPoint, startPoint ) );
F
Fabian Lange 已提交
43

44
		}
45

46
	},
47

48 49 50
	// To get accurate point with reference to
	// entire path distance at time t,
	// following has to be done:
51

52 53 54 55
	// 1. Length of each sub path have to be known
	// 2. Locate and identify type of curve
	// 3. Get t for the curve
	// 4. Return curve.getPointAt(t')
56

57
	getPoint: function ( t ) {
58

59 60 61
		var d = t * this.getLength();
		var curveLengths = this.getCurveLengths();
		var i = 0;
62

63
		// To think about boundaries points.
64

65
		while ( i < curveLengths.length ) {
66

67
			if ( curveLengths[ i ] >= d ) {
68

69 70
				var diff = curveLengths[ i ] - d;
				var curve = this.curves[ i ];
71

J
Joshua Koo 已提交
72 73
				var segmentLength = curve.getLength();
				var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
74

75
				return curve.getPointAt( u );
76

77
			}
78

79
			i ++;
80

81
		}
82

83
		return null;
84

85
		// loop where sum != 0, sum > d , sum+1 <d
86

87
	},
88

89 90 91
	// We cannot use the default THREE.Curve getPoint() with getLength() because in
	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
	// getPoint() depends on getLength
92

93
	getLength: function () {
94

95 96
		var lens = this.getCurveLengths();
		return lens[ lens.length - 1 ];
97

98
	},
99

R
rfm1201 已提交
100 101 102 103 104 105 106 107 108
	// cacheLengths must be recalculated.
	updateArcLengths: function () {

		this.needsUpdate = true;
		this.cacheLengths = null;
		this.getLengths();

	},

109 110
	// Compute lengths and cache them
	// We cannot overwrite getLengths() because UtoT mapping uses it.
111

112
	getCurveLengths: function () {
113

114
		// We use cache values if curves and cache array are same length
115

116
		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
117

118
			return this.cacheLengths;
119

120
		}
121

122 123
		// Get length of sub-curve
		// Push sums into cached array
124

125
		var lengths = [], sums = 0;
126

127
		for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
128

129 130
			sums += this.curves[ i ].getLength();
			lengths.push( sums );
131

132
		}
133

134
		this.cacheLengths = lengths;
135

136
		return lengths;
137

138
	},
139

J
Joshua Koo 已提交
140 141
	getSpacedPoints: function ( divisions ) {

142
		if ( isNaN( divisions ) ) divisions = 40;
J
Joshua Koo 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

		var points = [];

		for ( var i = 0; i <= divisions; i ++ ) {

			points.push( this.getPoint( i / divisions ) );

		}

		if ( this.autoClose ) {

			points.push( points[ 0 ] );

		}

		return points;

	},

	getPoints: function ( divisions ) {

		divisions = divisions || 12;

M
Mr.doob 已提交
166
		var points = [], last;
J
Joshua Koo 已提交
167 168 169

		for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {

M
Mr.doob 已提交
170
			var curve = curves[ i ];
R
Rich Harris 已提交
171 172 173
			var resolution = (curve && curve.isEllipseCurve) ? divisions * 2
				: (curve && curve.isLineCurve) ? 1
				: (curve && curve.isSplineCurve) ? divisions * curve.points.length
174 175 176
				: divisions;

			var pts = curve.getPoints( resolution );
J
Joshua Koo 已提交
177 178 179

			for ( var j = 0; j < pts.length; j++ ) {

M
Mr.doob 已提交
180 181 182 183 184 185
				var point = pts[ j ];

				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates

				points.push( point );
				last = point;
J
Joshua Koo 已提交
186 187 188 189 190

			}

		}

191
		if ( this.autoClose && points.length > 1 && !points[ points.length - 1 ].equals( points[ 0 ] ) ) {
J
Joshua Koo 已提交
192 193 194 195 196 197 198 199 200

			points.push( points[ 0 ] );

		}

		return points;

	},

201 202 203
	/**************************************************************
	 *	Create Geometries Helpers
	 **************************************************************/
204

205
	/// Generate geometry from path points (for Line or Points objects)
206

207
	createPointsGeometry: function ( divisions ) {
208

209 210
		var pts = this.getPoints( divisions );
		return this.createGeometry( pts );
211

212
	},
213

214
	// Generate geometry from equidistant sampling along the path
215

216
	createSpacedPointsGeometry: function ( divisions ) {
217

218 219
		var pts = this.getSpacedPoints( divisions );
		return this.createGeometry( pts );
220

221
	},
222

223
	createGeometry: function ( points ) {
224

R
Rich Harris 已提交
225
		var geometry = new Geometry();
226

227
		for ( var i = 0, l = points.length; i < l; i ++ ) {
228

229
			var point = points[ i ];
R
Rich Harris 已提交
230
			geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
231

232
		}
233

234
		return geometry;
235

M
Mr.doob 已提交
236
	}
237

238
} );
R
Rich Harris 已提交
239 240


241
export { CurvePath };