UNPKG

@numericelements/knot-sequence

Version:

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

204 lines (201 loc) 10.9 kB
import { __decorate, __metadata } from 'tslib'; import { AbstractOpenKnotSequence } from './AbstractOpenKnotSequence.js'; import { Knot } from './Knot.js'; import { NO_KNOT_OPEN_CURVE, NO_KNOT_CLOSED_CURVE, UNIFORM_OPENKNOTSEQUENCE, UNIFORMLYSPREADINTERKNOTS_OPENKNOTSEQUENCE, INCREASINGOPENKNOTSEQUENCE, INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, INCREASINGOPENKNOTSEQUENCECLOSEDCURVEALLKNOTS, INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS } from './KnotSequenceConstructorInterface.js'; import { EM_KNOTINDEX_INC_SEQ_TOO_LARGE, EM_ORIGIN_NORMALIZEDKNOT_SEQUENCE, EM_NOT_NORMALIZED_BASIS, EM_CUMULATIVE_KNOTMULTIPLICITY_ATEND, EM_CUMULATIVE_KNOTMULTIPLICITY_ATSTART, EM_NORMALIZED_BASIS_INTERVAL_NOTSUFFICIENT, EM_SIZE_KNOTSEQ_INCOMPATIBLE_SIZE_INTERNAL_STRICTLYINC_KNOTSEQ, EM_INDICES_FOR_EXTRACTION_OUTOF_RANGE } from './ErrorMessages/KnotSequences.js'; import { NormalizedBasisAtSequenceExtremity, KNOT_SEQUENCE_ORIGIN, UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA } from './namedConstants/KnotSequences.js'; import { KnotIndexStrictlyIncreasingSequence } from './KnotIndexStrictlyIncreasingSequence.js'; import { DEFAULT_KNOT_INDEX, DEFAULT_KNOT_ABSCISSA_VALUE } from './namedConstants/Knots.js'; import { adaptParameterRaiseKnotMultiplicity } from './KnotSequenceAndUtilities/adaptParameterRaiseKnotMultiplicity.js'; import { adaptParameterInsertKnot } from './KnotSequenceAndUtilities/adaptParameterInsertKnot.js'; import { adaptParameterDecrementKnotMultiplicity } from './KnotSequenceAndUtilities/adaptParameterDecrementKnotMultiplicity.js'; class AbstractIncreasingOpenKnotSequence extends AbstractOpenKnotSequence { constructor(maxMultiplicityOrder, knotParameters) { super(maxMultiplicityOrder, knotParameters); this._indexKnotOrigin = new KnotIndexStrictlyIncreasingSequence(DEFAULT_KNOT_INDEX); this._isSequenceUpToC0Discontinuity = false; if (knotParameters.type === NO_KNOT_OPEN_CURVE) { this._indexKnotOrigin.knotIndex = 0; } else if (knotParameters.type === NO_KNOT_CLOSED_CURVE) { this._indexKnotOrigin.knotIndex = this._maxMultiplicityOrder - 1; } else if (knotParameters.type === UNIFORM_OPENKNOTSEQUENCE) { this._indexKnotOrigin.knotIndex = this._maxMultiplicityOrder - 1; } else if (knotParameters.type === UNIFORMLYSPREADINTERKNOTS_OPENKNOTSEQUENCE) { this._indexKnotOrigin.knotIndex = 0; } else if (knotParameters.type === INCREASINGOPENKNOTSEQUENCE || knotParameters.type === INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY || knotParameters.type === INCREASINGOPENKNOTSEQUENCECLOSEDCURVEALLKNOTS || knotParameters.type === INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS) { if (knotParameters.type === INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY || knotParameters.type === INCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS) this._isSequenceUpToC0Discontinuity = true; this.generateKnotSequence(knotParameters); } } get allAbscissae() { const abscissae = []; for (const knot of this) { if (knot !== undefined) abscissae.push(knot); } return abscissae; } get indexKnotOrigin() { return this._indexKnotOrigin; } get isSequenceUpToC0Discontinuity() { return this._isSequenceUpToC0Discontinuity; } // temporary add setter while constructors of curve are set adequately set isSequenceUpToC0Discontinuity(isSequenceUpToC0Discontinuity) { this._isSequenceUpToC0Discontinuity = isSequenceUpToC0Discontinuity; } [Symbol.iterator]() { let nbKnots = 0; const knotIndicesKnotAbscissaChange = []; for (const multiplicity of this.multiplicities()) { nbKnots = nbKnots + multiplicity; knotIndicesKnotAbscissaChange.push(nbKnots); } const lastIndex = nbKnots - 1; let indexAbscissaChange = 0; let index = 0; return { next: () => { if (index <= lastIndex) { if (index === knotIndicesKnotAbscissaChange[indexAbscissaChange]) { indexAbscissaChange++; } index++; return { value: this.knotSequence[indexAbscissaChange].abscissa, done: false }; } else { index = 0; return { done: true }; } } }; } knotIndexInputParamAssessment(index, methodName) { if (index.knotIndex > (this.allAbscissae.length - 1)) { this.throwRangeErrorMessage(methodName, EM_KNOTINDEX_INC_SEQ_TOO_LARGE); } } updateNormalizedBasisOrigin() { const normalizedBasisAtStart = this.getKnotIndexNormalizedBasisAtSequenceStart(); let abscissaOrigin = DEFAULT_KNOT_ABSCISSA_VALUE; if (normalizedBasisAtStart.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.StrictlyNormalized) { abscissaOrigin = this.abscissaAtIndex(this.toKnotIndexIncreasingSequence(normalizedBasisAtStart.knot)); } if (abscissaOrigin !== KNOT_SEQUENCE_ORIGIN) this.throwRangeErrorMessage("checkNormalizedBasisOrigin", EM_ORIGIN_NORMALIZEDKNOT_SEQUENCE); } generateKnotSequence(knotParameters) { const minValueMaxMultiplicityOrder = 1; this.constructorInputMultOrderAssessment(minValueMaxMultiplicityOrder); this.constructorInputArrayAssessment(knotParameters); this.checkKnotIncreasingValues(knotParameters.knots); this.knotSequence.push(new Knot(knotParameters.knots[0], 1)); for (let i = 1; i < knotParameters.knots.length; i++) { if (knotParameters.knots[i] === this.knotSequence[this.knotSequence.length - 1].abscissa) { this.knotSequence[this.knotSequence.length - 1].multiplicity++; } else { this.knotSequence.push(new Knot(knotParameters.knots[i], 1)); } } this.checkMaxMultiplicityOrderConsistency(); this.checkSizeConsistency(knotParameters.knots); if (!this._isSequenceUpToC0Discontinuity) this.checkMaxKnotMultiplicityAtIntermediateKnots(); const { start: normalizedBasisAtStart, end: normalizedBasisAtEnd } = this.getKnotIndicesBoundingNormalizedBasis(); if (normalizedBasisAtEnd.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.NotNormalized || normalizedBasisAtStart.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.NotNormalized) { this.throwRangeErrorMessage("generateKnotSequence", EM_NOT_NORMALIZED_BASIS); } else if (normalizedBasisAtEnd.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.StrictlyNormalized) { this._uMax = this.abscissaAtIndex(this.toKnotIndexIncreasingSequence(normalizedBasisAtEnd.knot)); } else if (normalizedBasisAtEnd.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.OverDefined) { this.throwRangeErrorMessage("generateKnotSequence", EM_CUMULATIVE_KNOTMULTIPLICITY_ATEND); } if (normalizedBasisAtStart.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.StrictlyNormalized) { this._indexKnotOrigin = normalizedBasisAtStart.knot; } else if (normalizedBasisAtStart.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.OverDefined) { this.throwRangeErrorMessage("generateKnotSequence", EM_CUMULATIVE_KNOTMULTIPLICITY_ATSTART); } if (normalizedBasisAtEnd.knot.knotIndex <= normalizedBasisAtStart.knot.knotIndex) this.throwRangeErrorMessage("generateKnotSequence", EM_NORMALIZED_BASIS_INTERVAL_NOTSUFFICIENT); } checkSizeConsistency(knots) { let size = 0; for (const multiplicity of this.multiplicities()) { size += multiplicity; } if (size !== knots.length) this.throwRangeErrorMessage("checkSizeConsistency", EM_SIZE_KNOTSEQ_INCOMPATIBLE_SIZE_INTERNAL_STRICTLYINC_KNOTSEQ); } length() { let length = 0; for (const knot of this) { if (knot !== undefined) length++; } return length; } abscissaAtIndex(index) { this.knotIndexInputParamAssessment(index, "abscissaAtIndex"); let abscissa = UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA; let i = 0; for (const knot of this) { if (i === index.knotIndex && knot !== undefined) abscissa = knot; i++; } return abscissa; } extractSubsetOfAbscissae(knotStart, knotEnd) { let knots = []; if (!(knotStart.knotIndex >= 0) || !(knotEnd.knotIndex <= this.length() - 1) || !(knotStart.knotIndex <= knotEnd.knotIndex)) this.throwRangeErrorMessage("extractSubsetOfAbscissae", EM_INDICES_FOR_EXTRACTION_OUTOF_RANGE); let index = 0; for (const knot of this) { if (index >= knotStart.knotIndex && index <= knotEnd.knotIndex) { if (knot !== undefined) knots.push(knot); } index++; } return knots; } decrementKnotMultiplicityKnotArrayMutSeq(index, checkSequenceConsistency = true) { return super.decrementKnotMultiplicityKnotArrayMutSeq(index, checkSequenceConsistency); } raiseKnotMultiplicityKnotArrayMutSeq(arrayIndices, multiplicity = 1, checkSequenceConsistency = true) { return super.raiseKnotMultiplicityKnotArrayMutSeq(arrayIndices, multiplicity, checkSequenceConsistency); } insertKnotAbscissaArrayMutSeq(abscissa, multiplicity = 1) { return super.insertKnotAbscissaArrayMutSeq(abscissa, multiplicity); } } __decorate([ adaptParameterDecrementKnotMultiplicity(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Boolean]), __metadata("design:returntype", void 0) ], AbstractIncreasingOpenKnotSequence.prototype, "decrementKnotMultiplicityKnotArrayMutSeq", null); __decorate([ adaptParameterRaiseKnotMultiplicity(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Number, Boolean]), __metadata("design:returntype", void 0) ], AbstractIncreasingOpenKnotSequence.prototype, "raiseKnotMultiplicityKnotArrayMutSeq", null); __decorate([ adaptParameterInsertKnot(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Number]), __metadata("design:returntype", void 0) ], AbstractIncreasingOpenKnotSequence.prototype, "insertKnotAbscissaArrayMutSeq", null); export { AbstractIncreasingOpenKnotSequence };