UNPKG

@numericelements/knot-sequence

Version:

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

104 lines (101 loc) 5.41 kB
import { KNOT_SEQUENCE_ORIGIN, KNOT_COINCIDENCE_TOLERANCE, UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA } from './namedConstants/KnotSequences.js'; import { AbstractStrictlyIncreasingOpenKnotSequence } from './AbstractStrictlyIncreasingOpenKnotSequence.js'; import { STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, STRICTLYINCREASINGOPENKNOTSEQUENCE } from './KnotSequenceConstructorInterface.js'; import { EM_INCONSISTENT_ORIGIN_NONUNIFORM_KNOT_SEQUENCE, EM_U_OUTOF_KNOTSEQ_RANGE } from './ErrorMessages/KnotSequences.js'; import { KnotIndexStrictlyIncreasingSequence } from './KnotIndexStrictlyIncreasingSequence.js'; class StrictlyIncreasingOpenKnotSequenceOpenCurve extends AbstractStrictlyIncreasingOpenKnotSequence { constructor(maxMultiplicityOrder, knotParameters) { super(maxMultiplicityOrder, knotParameters); this.updateNormalizedBasisOrigin(); this.checkMaxMultiplicityOrderConsistency(); this.checkNonUniformKnotMultiplicityOrder(); this.checkUniformityOfKnotMultiplicity(); this.checkUniformityOfKnotSpacing(); } get isSequenceUpToC0Discontinuity() { return this._isSequenceUpToC0Discontinuity; } updateNormalizedBasisOrigin() { if (this.knotSequence[0].abscissa !== KNOT_SEQUENCE_ORIGIN && this._maxMultiplicityOrder === this.knotSequence[0].multiplicity) { this.throwRangeErrorMessage("checkCurveOrigin", EM_INCONSISTENT_ORIGIN_NONUNIFORM_KNOT_SEQUENCE); } else if (this.knotSequence[0].abscissa !== KNOT_SEQUENCE_ORIGIN) { super.updateNormalizedBasisOrigin(); } } 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 StrictlyIncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, knots: this.distinctAbscissae(), multiplicities: this.multiplicities() }); } else { return new StrictlyIncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: STRICTLYINCREASINGOPENKNOTSEQUENCE, knots: this.distinctAbscissae(), multiplicities: this.multiplicities() }); } } 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++; if (Math.abs(u - knot.abscissa) < KNOT_COINCIDENCE_TOLERANCE) { if (knot.abscissa === this.knotSequence[this.knotSequence.length - 1].abscissa) { index = this.knotSequence.length - 1; } index -= 1; break; } } return new KnotIndexStrictlyIncreasingSequence(index); } const indexAtUmax = this.getKnotIndexNormalizedBasisAtSequenceEnd(); index = this.findSpanWithAbscissaDistinctFromKnotStrictlyIncreasingKnotSequence(u, indexAtUmax.knot.knotIndex); } return new KnotIndexStrictlyIncreasingSequence(index); } revertKnotSequence() { const newKnotSequence = this.clone(); newKnotSequence.revertKnotSpacing(); return newKnotSequence; } decrementKnotMultiplicity(index, checkSequenceConsistency = true) { const newKnotSequence = this.clone(); newKnotSequence.decrementKnotMultiplicityMutSeq(index, checkSequenceConsistency); return newKnotSequence; } raiseKnotMultiplicity(index, multiplicity = 1, checkSequenceConsistency = true) { const newKnotSequence = this.clone(); newKnotSequence.raiseKnotMultiplicityKnotArrayMutSeq(index, multiplicity, checkSequenceConsistency); return newKnotSequence; } insertKnot(abscissae, multiplicity = 1) { const newKnotSequence = this.clone(); newKnotSequence.insertKnotAbscissaArrayMutSeq(abscissae, multiplicity); return newKnotSequence; } updateKnotSequenceThroughNormalizedBasisAnalysis() { const previousKnotSequence = this.knotSequence.slice(); this.updateKnotSequenceThroughNormalizedBasisAnalysisMutSeq(); const knotAbscissae = []; const multiplicities = []; for (const knot of this.knotSequence) { if (knot !== undefined) { knotAbscissae.push(knot.abscissa); multiplicities.push(knot.multiplicity); } } const updatedSeq = new StrictlyIncreasingOpenKnotSequenceOpenCurve(this._maxMultiplicityOrder, { type: STRICTLYINCREASINGOPENKNOTSEQUENCE, knots: knotAbscissae, multiplicities: multiplicities }); this.knotSequence = previousKnotSequence; return updatedSeq; } } export { StrictlyIncreasingOpenKnotSequenceOpenCurve };