Skip to content

⬅️ Back to Table of Contents

📄 CubicInterpolant.js

📊 Analysis Summary

Metric Count
🔧 Functions 2
🧱 Classes 1
📦 Imports 4
📊 Variables & Constants 23

📚 Table of Contents

🛠️ File Location:

📂 src/math/interpolants/CubicInterpolant.js

📦 Imports

Name Source
ZeroCurvatureEnding ../../constants.js
WrapAroundEnding ../../constants.js
ZeroSlopeEnding ../../constants.js
Interpolant ../Interpolant.js

Variables & Constants

Name Type Kind Value Exported
pp TypedArray let/var this.parameterPositions
iPrev number let/var i1 - 2
iNext any let/var i1 + 1
tPrev TypedArray let/var pp[ iPrev ]
tNext TypedArray let/var pp[ iNext ]
halfDt number let/var ( t1 - t0 ) * 0.5
stride TypedArray let/var this.valueSize
result TypedArray let/var this.resultBuffer
values TypedArray let/var this.sampleValues
stride TypedArray let/var this.valueSize
o1 number let/var i1 * stride
o0 number let/var o1 - stride
oP number let/var this._offsetPrev
oN number let/var this._offsetNext
wP number let/var this._weightPrev
wN number let/var this._weightNext
p number let/var ( t - t0 ) / ( t1 - t0 )
pp number let/var p * p
ppp number let/var pp * p
sP number let/var - wP * ppp + 2 * wP * pp - wP * p
s0 number let/var ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1
s1 number let/var ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p
sN number let/var wN * ppp - wN * pp

Functions

CubicInterpolant.intervalChanged_(i1: any, t0: any, t1: any): void

Parameters:

  • i1 any
  • t0 any
  • t1 any

Returns: void

Calls:

  • this.getSettings_

Internal Comments:

// f'(t0) = 0 (x3)
// use the other end of the curve (x6)
// f''(t0) = 0 a.k.a. Natural Spline (x3)
// f'(tN) = 0 (x3)
// f''(tN) = 0, a.k.a. Natural Spline (x3)

Code
intervalChanged_( i1, t0, t1 ) {

        const pp = this.parameterPositions;
        let iPrev = i1 - 2,
            iNext = i1 + 1,

            tPrev = pp[ iPrev ],
            tNext = pp[ iNext ];

        if ( tPrev === undefined ) {

            switch ( this.getSettings_().endingStart ) {

                case ZeroSlopeEnding:

                    // f'(t0) = 0
                    iPrev = i1;
                    tPrev = 2 * t0 - t1;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iPrev = pp.length - 2;
                    tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(t0) = 0 a.k.a. Natural Spline
                    iPrev = i1;
                    tPrev = t1;

            }

        }

        if ( tNext === undefined ) {

            switch ( this.getSettings_().endingEnd ) {

                case ZeroSlopeEnding:

                    // f'(tN) = 0
                    iNext = i1;
                    tNext = 2 * t1 - t0;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iNext = 1;
                    tNext = t1 + pp[ 1 ] - pp[ 0 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(tN) = 0, a.k.a. Natural Spline
                    iNext = i1 - 1;
                    tNext = t0;

            }

        }

        const halfDt = ( t1 - t0 ) * 0.5,
            stride = this.valueSize;

        this._weightPrev = halfDt / ( t0 - tPrev );
        this._weightNext = halfDt / ( tNext - t1 );
        this._offsetPrev = iPrev * stride;
        this._offsetNext = iNext * stride;

    }

CubicInterpolant.interpolate_(i1: any, t0: any, t: any, t1: any): TypedArray

Parameters:

  • i1 any
  • t0 any
  • t any
  • t1 any

Returns: TypedArray

Internal Comments:

// evaluate polynomials (x2)
// combine data linearly

Code
interpolate_( i1, t0, t, t1 ) {

        const result = this.resultBuffer,
            values = this.sampleValues,
            stride = this.valueSize,

            o1 = i1 * stride,       o0 = o1 - stride,
            oP = this._offsetPrev,  oN = this._offsetNext,
            wP = this._weightPrev,  wN = this._weightNext,

            p = ( t - t0 ) / ( t1 - t0 ),
            pp = p * p,
            ppp = pp * p;

        // evaluate polynomials

        const sP = - wP * ppp + 2 * wP * pp - wP * p;
        const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
        const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
        const sN = wN * ppp - wN * pp;

        // combine data linearly

        for ( let i = 0; i !== stride; ++ i ) {

            result[ i ] =
                    sP * values[ oP + i ] +
                    s0 * values[ o0 + i ] +
                    s1 * values[ o1 + i ] +
                    sN * values[ oN + i ];

        }

        return result;

    }

Classes

CubicInterpolant

Class Code
class CubicInterpolant extends Interpolant {

    /**
     * Constructs a new cubic interpolant.
     *
     * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
     * @param {TypedArray} sampleValues - The sample values.
     * @param {number} sampleSize - The sample size
     * @param {TypedArray} [resultBuffer] - The result buffer.
     */
    constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {

        super( parameterPositions, sampleValues, sampleSize, resultBuffer );

        this._weightPrev = - 0;
        this._offsetPrev = - 0;
        this._weightNext = - 0;
        this._offsetNext = - 0;

        this.DefaultSettings_ = {

            endingStart: ZeroCurvatureEnding,
            endingEnd: ZeroCurvatureEnding

        };

    }

    intervalChanged_( i1, t0, t1 ) {

        const pp = this.parameterPositions;
        let iPrev = i1 - 2,
            iNext = i1 + 1,

            tPrev = pp[ iPrev ],
            tNext = pp[ iNext ];

        if ( tPrev === undefined ) {

            switch ( this.getSettings_().endingStart ) {

                case ZeroSlopeEnding:

                    // f'(t0) = 0
                    iPrev = i1;
                    tPrev = 2 * t0 - t1;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iPrev = pp.length - 2;
                    tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(t0) = 0 a.k.a. Natural Spline
                    iPrev = i1;
                    tPrev = t1;

            }

        }

        if ( tNext === undefined ) {

            switch ( this.getSettings_().endingEnd ) {

                case ZeroSlopeEnding:

                    // f'(tN) = 0
                    iNext = i1;
                    tNext = 2 * t1 - t0;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iNext = 1;
                    tNext = t1 + pp[ 1 ] - pp[ 0 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(tN) = 0, a.k.a. Natural Spline
                    iNext = i1 - 1;
                    tNext = t0;

            }

        }

        const halfDt = ( t1 - t0 ) * 0.5,
            stride = this.valueSize;

        this._weightPrev = halfDt / ( t0 - tPrev );
        this._weightNext = halfDt / ( tNext - t1 );
        this._offsetPrev = iPrev * stride;
        this._offsetNext = iNext * stride;

    }

    interpolate_( i1, t0, t, t1 ) {

        const result = this.resultBuffer,
            values = this.sampleValues,
            stride = this.valueSize,

            o1 = i1 * stride,       o0 = o1 - stride,
            oP = this._offsetPrev,  oN = this._offsetNext,
            wP = this._weightPrev,  wN = this._weightNext,

            p = ( t - t0 ) / ( t1 - t0 ),
            pp = p * p,
            ppp = pp * p;

        // evaluate polynomials

        const sP = - wP * ppp + 2 * wP * pp - wP * p;
        const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
        const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
        const sN = wN * ppp - wN * pp;

        // combine data linearly

        for ( let i = 0; i !== stride; ++ i ) {

            result[ i ] =
                    sP * values[ oP + i ] +
                    s0 * values[ o0 + i ] +
                    s1 * values[ o1 + i ] +
                    sN * values[ oN + i ];

        }

        return result;

    }

}

Methods

intervalChanged_(i1: any, t0: any, t1: any): void
Code
intervalChanged_( i1, t0, t1 ) {

        const pp = this.parameterPositions;
        let iPrev = i1 - 2,
            iNext = i1 + 1,

            tPrev = pp[ iPrev ],
            tNext = pp[ iNext ];

        if ( tPrev === undefined ) {

            switch ( this.getSettings_().endingStart ) {

                case ZeroSlopeEnding:

                    // f'(t0) = 0
                    iPrev = i1;
                    tPrev = 2 * t0 - t1;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iPrev = pp.length - 2;
                    tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(t0) = 0 a.k.a. Natural Spline
                    iPrev = i1;
                    tPrev = t1;

            }

        }

        if ( tNext === undefined ) {

            switch ( this.getSettings_().endingEnd ) {

                case ZeroSlopeEnding:

                    // f'(tN) = 0
                    iNext = i1;
                    tNext = 2 * t1 - t0;

                    break;

                case WrapAroundEnding:

                    // use the other end of the curve
                    iNext = 1;
                    tNext = t1 + pp[ 1 ] - pp[ 0 ];

                    break;

                default: // ZeroCurvatureEnding

                    // f''(tN) = 0, a.k.a. Natural Spline
                    iNext = i1 - 1;
                    tNext = t0;

            }

        }

        const halfDt = ( t1 - t0 ) * 0.5,
            stride = this.valueSize;

        this._weightPrev = halfDt / ( t0 - tPrev );
        this._weightNext = halfDt / ( tNext - t1 );
        this._offsetPrev = iPrev * stride;
        this._offsetNext = iNext * stride;

    }
interpolate_(i1: any, t0: any, t: any, t1: any): TypedArray
Code
interpolate_( i1, t0, t, t1 ) {

        const result = this.resultBuffer,
            values = this.sampleValues,
            stride = this.valueSize,

            o1 = i1 * stride,       o0 = o1 - stride,
            oP = this._offsetPrev,  oN = this._offsetNext,
            wP = this._weightPrev,  wN = this._weightNext,

            p = ( t - t0 ) / ( t1 - t0 ),
            pp = p * p,
            ppp = pp * p;

        // evaluate polynomials

        const sP = - wP * ppp + 2 * wP * pp - wP * p;
        const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
        const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
        const sN = wN * ppp - wN * pp;

        // combine data linearly

        for ( let i = 0; i !== stride; ++ i ) {

            result[ i ] =
                    sP * values[ oP + i ] +
                    s0 * values[ o0 + i ] +
                    s1 * values[ o1 + i ] +
                    sN * values[ oN + i ];

        }

        return result;

    }