@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
JavaScript
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 };