|
|
@@ -4,58 +4,81 @@ import { Vector3 } from '../../math/Vector3.js';
|
|
|
import { Matrix4 } from '../../math/Matrix4.js';
|
|
|
|
|
|
/**
|
|
|
- * Extensible curve object.
|
|
|
+ * An abstract base class for creating an analytic curve object that contains methods
|
|
|
+ * for interpolation.
|
|
|
*
|
|
|
- * Some common of curve methods:
|
|
|
- * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
|
|
|
- * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
|
|
|
- * .getPoints(), .getSpacedPoints()
|
|
|
- * .getLength()
|
|
|
- * .updateArcLengths()
|
|
|
- *
|
|
|
- * This following curves inherit from THREE.Curve:
|
|
|
- *
|
|
|
- * -- 2D curves --
|
|
|
- * THREE.ArcCurve
|
|
|
- * THREE.CubicBezierCurve
|
|
|
- * THREE.EllipseCurve
|
|
|
- * THREE.LineCurve
|
|
|
- * THREE.QuadraticBezierCurve
|
|
|
- * THREE.SplineCurve
|
|
|
- *
|
|
|
- * -- 3D curves --
|
|
|
- * THREE.CatmullRomCurve3
|
|
|
- * THREE.CubicBezierCurve3
|
|
|
- * THREE.LineCurve3
|
|
|
- * THREE.QuadraticBezierCurve3
|
|
|
- *
|
|
|
- * A series of curves can be represented as a THREE.CurvePath.
|
|
|
- *
|
|
|
- **/
|
|
|
-
|
|
|
+ * @abstract
|
|
|
+ */
|
|
|
class Curve {
|
|
|
|
|
|
+ /**
|
|
|
+ * Constructs a new curve.
|
|
|
+ */
|
|
|
constructor() {
|
|
|
|
|
|
+ /**
|
|
|
+ * The type property is used for detecting the object type
|
|
|
+ * in context of serialization/deserialization.
|
|
|
+ *
|
|
|
+ * @type {string}
|
|
|
+ * @readonly
|
|
|
+ */
|
|
|
this.type = 'Curve';
|
|
|
|
|
|
+ /**
|
|
|
+ * This value determines the amount of divisions when calculating the
|
|
|
+ * cumulative segment lengths of a curve via {@link Curve#getLengths}. To ensure
|
|
|
+ * precision when using methods like {@link Curve#getSpacedPoints}, it is
|
|
|
+ * recommended to increase the value of this property if the curve is very large.
|
|
|
+ *
|
|
|
+ * @type {number}
|
|
|
+ * @default 200
|
|
|
+ */
|
|
|
this.arcLengthDivisions = 200;
|
|
|
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * Must be set to `true` if the curve parameters have changed.
|
|
|
+ *
|
|
|
+ * @type {boolean}
|
|
|
+ * @default false
|
|
|
+ */
|
|
|
+ this.needsUpdate = false;
|
|
|
|
|
|
- // Virtual base class method to overwrite and implement in subclasses
|
|
|
- // - t [0 .. 1]
|
|
|
+ /**
|
|
|
+ * An internal cache that holds precomputed curve length values.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @type {?Array<number>}
|
|
|
+ * @default null
|
|
|
+ */
|
|
|
+ this.cacheArcLengths = null;
|
|
|
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This method returns a vector in 2D or 3D space (depending on the curve definition)
|
|
|
+ * for the given interpolation factor.
|
|
|
+ *
|
|
|
+ * @abstract
|
|
|
+ * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
|
|
|
+ * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
|
|
|
+ * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
|
|
|
+ */
|
|
|
getPoint( /* t, optionalTarget */ ) {
|
|
|
|
|
|
console.warn( 'THREE.Curve: .getPoint() not implemented.' );
|
|
|
- return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Get point at relative position in curve according to arc length
|
|
|
- // - u [0 .. 1]
|
|
|
-
|
|
|
+ /**
|
|
|
+ * This method returns a vector in 2D or 3D space (depending on the curve definition)
|
|
|
+ * for the given interpolation factor. Unlike {@link Curve#getPoint}, this method honors the length
|
|
|
+ * of the curve which equidistant samples.
|
|
|
+ *
|
|
|
+ * @param {number} u - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
|
|
|
+ * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
|
|
|
+ * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
|
|
|
+ */
|
|
|
getPointAt( u, optionalTarget ) {
|
|
|
|
|
|
const t = this.getUtoTmapping( u );
|
|
|
@@ -63,8 +86,13 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Get sequence of points using getPoint( t )
|
|
|
-
|
|
|
+ /**
|
|
|
+ * This method samples the curve via {@link Curve#getPoint} and returns an array of points representing
|
|
|
+ * the curve shape.
|
|
|
+ *
|
|
|
+ * @param {number} [divisions=5] - The number of divisions.
|
|
|
+ * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
|
|
|
+ */
|
|
|
getPoints( divisions = 5 ) {
|
|
|
|
|
|
const points = [];
|
|
|
@@ -81,6 +109,14 @@ class Curve {
|
|
|
|
|
|
// Get sequence of points using getPointAt( u )
|
|
|
|
|
|
+ /**
|
|
|
+ * This method samples the curve via {@link Curve#getPointAt} and returns an array of points representing
|
|
|
+ * the curve shape. Unlike {@link Curve#getPoints}, this method returns equi-spaced points across the entire
|
|
|
+ * curve.
|
|
|
+ *
|
|
|
+ * @param {number} [divisions=5] - The number of divisions.
|
|
|
+ * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
|
|
|
+ */
|
|
|
getSpacedPoints( divisions = 5 ) {
|
|
|
|
|
|
const points = [];
|
|
|
@@ -95,8 +131,11 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Get total curve arc length
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Returns the total arc length of the curve.
|
|
|
+ *
|
|
|
+ * @return {number} The length of the curve..
|
|
|
+ */
|
|
|
getLength() {
|
|
|
|
|
|
const lengths = this.getLengths();
|
|
|
@@ -104,8 +143,12 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Get list of cumulative segment lengths
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Returns an array of cumulative segment lengths of the curve.
|
|
|
+ *
|
|
|
+ * @param {number} [divisions=this.arcLengthDivisions] - The number of divisions.
|
|
|
+ * @return {Array<number>} An array holding the cumulative segment lengths.
|
|
|
+ */
|
|
|
getLengths( divisions = this.arcLengthDivisions ) {
|
|
|
|
|
|
if ( this.cacheArcLengths &&
|
|
|
@@ -139,6 +182,12 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Update the cumulative segment distance cache. The method must be called
|
|
|
+ * every time curve parameters are changed. If an updated curve is part of a
|
|
|
+ * composed curve like {@link CurvePath}, this method must be called on the
|
|
|
+ * composed curve, too.
|
|
|
+ */
|
|
|
updateArcLengths() {
|
|
|
|
|
|
this.needsUpdate = true;
|
|
|
@@ -146,9 +195,16 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
|
|
|
-
|
|
|
- getUtoTmapping( u, distance ) {
|
|
|
+ /**
|
|
|
+ * Given an interpolation factor in the range `[0,1]`, this method returns an updated
|
|
|
+ * interpolation factor in the same range that can be ued to sample equidistant points
|
|
|
+ * from a curve.
|
|
|
+ *
|
|
|
+ * @param {number} u - The interpolation factor.
|
|
|
+ * @param {?number} distance - An optional distance on the curve.
|
|
|
+ * @return {number} The updated interpolation factor.
|
|
|
+ */
|
|
|
+ getUtoTmapping( u, distance = null ) {
|
|
|
|
|
|
const arcLengths = this.getLengths();
|
|
|
|
|
|
@@ -223,11 +279,16 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Returns a unit vector tangent at t
|
|
|
- // In case any sub curve does not implement its tangent derivation,
|
|
|
- // 2 points a small delta apart will be used to find its gradient
|
|
|
- // which seems to give a reasonable approximation
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Returns a unit vector tangent for the given interpolation factor.
|
|
|
+ * If the derived curve does not implement its tangent derivation,
|
|
|
+ * two points a small delta apart will be used to find its gradient
|
|
|
+ * which seems to give a reasonable approximation.
|
|
|
+ *
|
|
|
+ * @param {number} t - The interpolation factor.
|
|
|
+ * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
|
|
|
+ * @return {(Vector2|Vector3)} The tagent vector.
|
|
|
+ */
|
|
|
getTangent( t, optionalTarget ) {
|
|
|
|
|
|
const delta = 0.0001;
|
|
|
@@ -250,6 +311,14 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Same as {@link Curve#getTangent} but with equidistant samples.
|
|
|
+ *
|
|
|
+ * @param {number} u - The interpolation factor.
|
|
|
+ * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
|
|
|
+ * @return {(Vector2|Vector3)} The tagent vector.
|
|
|
+ * @see {@link Curve#getPointAt}
|
|
|
+ */
|
|
|
getTangentAt( u, optionalTarget ) {
|
|
|
|
|
|
const t = this.getUtoTmapping( u );
|
|
|
@@ -257,7 +326,15 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
- computeFrenetFrames( segments, closed ) {
|
|
|
+ /**
|
|
|
+ * Generates the Frenet Frames. Requires a curve definition in 3D space. Used
|
|
|
+ * in geometries like {@link TubeGeometry} or {@link ExtrudeGeometry}.
|
|
|
+ *
|
|
|
+ * @param {number} segments - The number of segments.
|
|
|
+ * @param {boolean} [closed=false] - Whether the curve is closed or not.
|
|
|
+ * @return {{tangents: Array<Vector3>, normals: Array<Vector3>, binormals: Array<Vector3>}} The Frenet Frames.
|
|
|
+ */
|
|
|
+ computeFrenetFrames( segments, closed = false ) {
|
|
|
|
|
|
// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
|
|
|
|
|
|
@@ -371,12 +448,23 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Returns a new curve with copied values from this instance.
|
|
|
+ *
|
|
|
+ * @return {Curve} A clone of this instance.
|
|
|
+ */
|
|
|
clone() {
|
|
|
|
|
|
return new this.constructor().copy( this );
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Copies the values of the given curve to this instance.
|
|
|
+ *
|
|
|
+ * @param {Curve} source - The curve to copy.
|
|
|
+ * @return {Curve} A reference to this curve.
|
|
|
+ */
|
|
|
copy( source ) {
|
|
|
|
|
|
this.arcLengthDivisions = source.arcLengthDivisions;
|
|
|
@@ -385,6 +473,12 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Serializes the curve into JSON.
|
|
|
+ *
|
|
|
+ * @return {Object} A JSON object representing the serialized curve.
|
|
|
+ * @see {@link ObjectLoader#parse}
|
|
|
+ */
|
|
|
toJSON() {
|
|
|
|
|
|
const data = {
|
|
|
@@ -402,6 +496,12 @@ class Curve {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Deserializes the curve from the given JSON.
|
|
|
+ *
|
|
|
+ * @param {Object} json - The JSON holding the serialized curve.
|
|
|
+ * @return {Curve} A reference to this curve.
|
|
|
+ */
|
|
|
fromJSON( json ) {
|
|
|
|
|
|
this.arcLengthDivisions = json.arcLengthDivisions;
|