@numericelements/knot-sequence
Version:
A library for generating and manipulating knot sequences for b-spline curves and surfaces
171 lines (168 loc) • 10.2 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, STRICTLYINCREASINGOPENKNOTSEQUENCE, STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY, STRICTLYINCREASINGOPENKNOTSEQUENCECLOSEDCURVEALLKNOTS, STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS } from './KnotSequenceConstructorInterface.js';
import { EM_KNOT_MULTIPLICITY_OUT_OF_RANGE, EM_ORIGIN_NORMALIZEDKNOT_SEQUENCE, EM_NOT_NORMALIZED_BASIS, EM_CUMULATIVE_KNOTMULTIPLICITY_ATEND, EM_CUMULATIVE_KNOTMULTIPLICITY_ATSTART, EM_NORMALIZED_BASIS_INTERVAL_NOTSUFFICIENT, EM_SIZENORMALIZED_BSPLINEBASIS, EM_KNOTINDEX_INC_SEQ_TOO_LARGE } 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 { adaptParameterInsertKnot } from './KnotSequenceAndUtilities/adaptParameterInsertKnot.js';
import { adaptParameterRaiseKnotMultiplicity } from './KnotSequenceAndUtilities/adaptParameterRaiseKnotMultiplicity.js';
import { WarningLog } from './errorProcessing/ErrorLoging.js';
import { WM_GEOMETRIC_CONSTRAINTS_POLYGON_VERTICES } from './WarningMessages/KnotSequences.js';
class AbstractStrictlyIncreasingOpenKnotSequence 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 === STRICTLYINCREASINGOPENKNOTSEQUENCE || knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY ||
knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCECLOSEDCURVEALLKNOTS || knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS) {
if (knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY || knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS)
this._isSequenceUpToC0Discontinuity = true;
this.generateKnotSequence(knotParameters);
}
}
get allAbscissae() {
const abscissae = [];
for (const knot of this) {
if (knot !== undefined)
abscissae.push(knot.abscissa);
}
return abscissae;
}
get indexKnotOrigin() {
return this._indexKnotOrigin;
}
[Symbol.iterator]() {
const lastIndex = this.knotSequence.length - 1;
let index = 0;
return {
next: () => {
if (index <= lastIndex) {
const abscissa = this.knotSequence[index].abscissa;
const multiplicity = this.knotSequence[index].multiplicity;
index++;
return { value: { abscissa: abscissa, multiplicity: multiplicity },
done: false };
}
else {
index = 0;
return { done: true };
}
}
};
}
checkKnotMultiplicities(multiplicities) {
for (let i = 0; i < multiplicities.length; i++) {
if (multiplicities[i] <= 0)
this.throwRangeErrorMessage("checkKnotMultiplicities", EM_KNOT_MULTIPLICITY_OUT_OF_RANGE);
}
}
updateNormalizedBasisOrigin() {
const normalizedBasisAtStart = this.getKnotIndexNormalizedBasisAtSequenceStart();
let abscissaOrigin = DEFAULT_KNOT_ABSCISSA_VALUE;
if (normalizedBasisAtStart.basisAtSeqExt === NormalizedBasisAtSequenceExtremity.StrictlyNormalized) {
abscissaOrigin = this.abscissaAtIndex(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.checkKnotStrictlyIncreasingValues(knotParameters.knots);
this.checkKnotMultiplicities(knotParameters.multiplicities);
for (let i = 0; i < knotParameters.knots.length; i++) {
this.knotSequence.push(new Knot(knotParameters.knots[i], knotParameters.multiplicities[i]));
}
this.checkMaxMultiplicityOrderConsistency();
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(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);
if (knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCECLOSEDCURVEALLKNOTS || knotParameters.type === STRICTLYINCREASINGOPENKNOTSEQUENCE_UPTOC0DISCONTINUITY_CLOSEDCURVEALLKNOTS) {
this.checkKnotMultiplicitiesAtNormalizedBasisBoundaries();
const periodicKnotLength = normalizedBasisAtEnd.knot.knotIndex - normalizedBasisAtStart.knot.knotIndex;
if (this._maxMultiplicityOrder === 2 && periodicKnotLength < 3)
this.throwRangeErrorMessage("generateKnotSequence", EM_SIZENORMALIZED_BSPLINEBASIS);
let cumulative_multiplicities = 0;
for (let i = this._indexKnotOrigin.knotIndex + 1; i < this._indexKnotOrigin.knotIndex + periodicKnotLength; i++) {
cumulative_multiplicities += knotParameters.multiplicities[i];
}
if (cumulative_multiplicities < (this._maxMultiplicityOrder - this.knotMultiplicity(this._indexKnotOrigin))) {
const warning = new WarningLog(this.constructor.name, "generateKnotSequence", WM_GEOMETRIC_CONSTRAINTS_POLYGON_VERTICES);
warning.logMessage();
if (this.knotMultiplicity(this._indexKnotOrigin) === 1)
this.throwRangeErrorMessage("generateKnotSequence", EM_SIZENORMALIZED_BSPLINEBASIS);
}
}
}
length() {
return this.knotSequence.length;
}
knotIndexInputParamAssessment(index, methodName) {
if (index.knotIndex > (this.allAbscissae.length - 1)) {
this.throwRangeErrorMessage(methodName, EM_KNOTINDEX_INC_SEQ_TOO_LARGE);
}
}
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.abscissa;
i++;
}
return abscissa;
}
raiseKnotMultiplicityKnotArrayMutSeq(arrayIndices, multiplicity = 1, checkSequenceConsistency = true) {
return super.raiseKnotMultiplicityKnotArrayMutSeq(arrayIndices, multiplicity, checkSequenceConsistency);
}
insertKnotAbscissaArrayMutSeq(abscissa, multiplicity = 1) {
return super.insertKnotAbscissaArrayMutSeq(abscissa, multiplicity);
}
}
__decorate([
adaptParameterRaiseKnotMultiplicity(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Number, Boolean]),
__metadata("design:returntype", void 0)
], AbstractStrictlyIncreasingOpenKnotSequence.prototype, "raiseKnotMultiplicityKnotArrayMutSeq", null);
__decorate([
adaptParameterInsertKnot(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, Number]),
__metadata("design:returntype", void 0)
], AbstractStrictlyIncreasingOpenKnotSequence.prototype, "insertKnotAbscissaArrayMutSeq", null);
export { AbstractStrictlyIncreasingOpenKnotSequence };