UNPKG

@numericelements/knot-sequence

Version:

A library for generating and manipulating knot sequences for b-spline curves and surfaces

109 lines (106 loc) 5.74 kB
import { KNOT_SEQUENCE_ORIGIN, KNOT_COINCIDENCE_TOLERANCE, UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA } from './namedConstants/KnotSequences.js'; import { AbstractIncreasingOpenKnotSequence } from './AbstractIncreasingOpenKnotSequence.js'; import { KnotIndexIncreasingSequence } from './KnotIndexIncreasingSequence.js'; import { INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, INCREASINGOPENKNOTSEQUENCE } from './KnotSequenceConstructorInterface.js'; import { EM_U_OUTOF_KNOTSEQ_RANGE } from './ErrorMessages/KnotSequences.js'; import { fromIncreasingToStrictlyIncreasingOpenKnotSequenceOC } from './KnotSequenceAndUtilities/fromIncreasingToStrictlyIncreasingOpenKnotSequenceOC.js'; import { KnotIndexStrictlyIncreasingSequence } from './KnotIndexStrictlyIncreasingSequence.js'; class IncreasingOpenKnotSequenceOpenCurve extends AbstractIncreasingOpenKnotSequence { constructor(maxMultiplicityOrder, knotParameters) { super(maxMultiplicityOrder, knotParameters); if (knotParameters.type !== INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY) this.updateNormalizedBasisOrigin(); this.checkNonUniformKnotMultiplicityOrder(); this.checkUniformityOfKnotMultiplicity(); this.checkUniformityOfKnotSpacing(); } checkNonUniformKnotMultiplicityOrder() { this._isKnotMultiplicityNonUniform = false; if (this.knotSequence[0].multiplicity === this._maxMultiplicityOrder && this.knotSequence[this.knotSequence.length - 1].multiplicity === this._maxMultiplicityOrder) this._isKnotMultiplicityNonUniform = true; } clone() { if (this._isSequenceUpToC0Discontinuity) { return new IncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, knots: this.allAbscissae }); } else { return new IncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: INCREASINGOPENKNOTSEQUENCE, knots: this.allAbscissae }); } } toKnotIndexStrictlyIncreasingSequence(index) { const strictlyIncreasingKnotSequence = fromIncreasingToStrictlyIncreasingOpenKnotSequenceOC(this); const abscissa = this.abscissaAtIndex(index); let i = 0; for (const knot of strictlyIncreasingKnotSequence.allAbscissae) { if (knot !== undefined) { if (knot === abscissa) break; i++; } } return new KnotIndexStrictlyIncreasingSequence(i); } findSpan(u) { let index = UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA; if (u < KNOT_SEQUENCE_ORIGIN || u > this._uMax) { this.throwRangeErrorMessage("findSpan", EM_U_OUTOF_KNOTSEQ_RANGE); } else { if (this.isAbscissaCoincidingWithKnot(u)) { index = 0; for (const knot of this.knotSequence) { index += knot.multiplicity; if (Math.abs(u - knot.abscissa) < KNOT_COINCIDENCE_TOLERANCE) { if (knot.abscissa === this.knotSequence[this.knotSequence.length - 1].abscissa) { index -= this.knotSequence[this.knotSequence.length - 1].multiplicity; } const curveDegree = this._maxMultiplicityOrder - 1; if (this.isKnotMultiplicityUniform && index === (this.knotSequence.length - curveDegree)) index -= 1; index -= 1; break; } } return new KnotIndexIncreasingSequence(index); } const indexAtUmax = this.getKnotIndexNormalizedBasisAtSequenceEnd(); index = this.findSpanWithAbscissaDistinctFromKnotIncreasingKnotSequence(u, indexAtUmax.knot.knotIndex); } return new KnotIndexIncreasingSequence(index); } revertKnotSequence() { const newKnotSequence = this.clone(); newKnotSequence.revertKnotSpacing(); return newKnotSequence; } decrementKnotMultiplicity(index, checkSequenceConsistency = true) { const newKnotSequence = this.clone(); newKnotSequence.decrementKnotMultiplicityKnotArrayMutSeq(index, checkSequenceConsistency); return newKnotSequence; } raiseKnotMultiplicity(arrayIndices, multiplicity = 1, checkSequenceConsistency = true) { const newKnotSequence = this.clone(); newKnotSequence.raiseKnotMultiplicityKnotArrayMutSeq(arrayIndices, multiplicity, checkSequenceConsistency); return newKnotSequence; } insertKnot(arrayAbscissae, multplicity = 1) { const newKnotSequence = this.clone(); newKnotSequence.insertKnotAbscissaArrayMutSeq(arrayAbscissae, multplicity); return newKnotSequence; } updateKnotSequenceThroughNormalizedBasisAnalysis() { const previousKnotSequence = this.knotSequence.slice(); this.updateKnotSequenceThroughNormalizedBasisAnalysisMutSeq(); const knotAbscissae = []; for (const knot of this.allAbscissae) { knotAbscissae.push(knot); } let updatedSeq = new IncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: INCREASINGOPENKNOTSEQUENCE, knots: knotAbscissae }); if (this._isSequenceUpToC0Discontinuity) updatedSeq = new IncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, knots: knotAbscissae }); this.knotSequence = previousKnotSequence; return updatedSeq; } } export { IncreasingOpenKnotSequenceOpenCurve };