@numericelements/knot-sequence
Version:
A library for generating and manipulating knot sequences for b-spline curves and surfaces
219 lines (215 loc) • 10.4 kB
JavaScript
'use strict';
var ErrorLoging = require('./errorProcessing/ErrorLoging.cjs');
var KnotSequences$1 = require('./namedConstants/KnotSequences.cjs');
var AbstractPeriodicKnotSequence = require('./AbstractPeriodicKnotSequence.cjs');
var Knot = require('./Knot.cjs');
var KnotSequenceConstructorInterface = require('./KnotSequenceConstructorInterface.cjs');
var fromIncreasingPeriodicToStrictlyIncreasingPeriodicKnotSequence = require('./KnotSequenceAndUtilities/fromIncreasingPeriodicToStrictlyIncreasingPeriodicKnotSequence.cjs');
var KnotSequences = require('./ErrorMessages/KnotSequences.cjs');
var KnotIndexStrictlyIncreasingSequence = require('./KnotIndexStrictlyIncreasingSequence.cjs');
var KnotIndexIncreasingSequence = require('./KnotIndexIncreasingSequence.cjs');
var KnotSequences$2 = require('./WarningMessages/KnotSequences.cjs');
class IncreasingPeriodicKnotSequenceClosedCurve extends AbstractPeriodicKnotSequence.AbstractPeriodicKnotSequence {
constructor(maxMultiplicityOrder, knotParameters) {
super(maxMultiplicityOrder, knotParameters);
this._indexKnotOrigin = new KnotIndexStrictlyIncreasingSequence.KnotIndexStrictlyIncreasingSequence(0);
if (knotParameters.type === KnotSequenceConstructorInterface.INCREASINGPERIODICKNOTSEQUENCE) {
this.generateKnotSequence(knotParameters);
this.checkKnotMultiplicitiesAtNormalizedBasisBoundaries();
}
this.checkUniformityOfKnotMultiplicity();
this.checkUniformityOfKnotSpacing();
this.checkNonUniformKnotMultiplicityOrder();
this.checkNormalizedBasisOrigin();
}
get allAbscissae() {
const abscissae = [];
for (const knot of this) {
if (knot !== undefined)
abscissae.push(knot);
}
return abscissae;
}
[Symbol.iterator]() {
let knotAmount = 0;
const knotIndicesKnotAbscissaChange = [];
for (const multiplicity of this.multiplicities()) {
knotAmount = knotAmount + multiplicity;
knotIndicesKnotAbscissaChange.push(knotAmount);
}
const lastIndex = knotAmount - 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 };
}
}
};
}
clone() {
return new IncreasingPeriodicKnotSequenceClosedCurve(this._maxMultiplicityOrder, { type: KnotSequenceConstructorInterface.INCREASINGPERIODICKNOTSEQUENCE, periodicKnots: this.allAbscissae });
}
length() {
let length = 0;
for (const knot of this) {
if (knot !== undefined)
length++;
}
return length;
}
knotIndexInputParamAssessment(index, methodName) {
if (index.knotIndex > (this.allAbscissae.length - 1)) {
this.throwRangeErrorMessage(methodName, KnotSequences.EM_KNOTINDEX_INC_SEQ_TOO_LARGE);
}
}
generateKnotSequence(knotParameters) {
const minValueMaxMultiplicityOrder = 1;
this.constructorInputMultOrderAssessment(minValueMaxMultiplicityOrder);
this.constructorInputArrayAssessment(knotParameters);
this.checkKnotIncreasingValues(knotParameters.periodicKnots);
this.knotSequence.push(new Knot.Knot(knotParameters.periodicKnots[0], 1));
for (let i = 1; i < knotParameters.periodicKnots.length; i++) {
if (knotParameters.periodicKnots[i] === this.knotSequence[this.knotSequence.length - 1].abscissa) {
this.knotSequence[this.knotSequence.length - 1].multiplicity++;
}
else {
this.knotSequence.push(new Knot.Knot(knotParameters.periodicKnots[i], 1));
}
}
this.checkMaxMultiplicityOrderConsistency();
const cumulative_multiplicities = knotParameters.periodicKnots.length - this.knotSequence[this.knotSequence.length - 1].multiplicity;
if ((cumulative_multiplicities < this._maxMultiplicityOrder && this._maxMultiplicityOrder > 1) ||
(cumulative_multiplicities < (this._maxMultiplicityOrder + 1) && this._maxMultiplicityOrder === 1)) {
this.throwRangeErrorMessage("generateKnotSequence", KnotSequences.EM_KNOTSEQ_MULTIPLICITIES_INCOMPATIBLE_NORMALIZEDBASIS);
}
this._uMax = this.knotSequence[this.knotSequence.length - 1].abscissa;
this.checkNormalizedBasisOrigin();
this.checkKnotMultiplicitiesAtNormalizedBasisBoundaries();
}
raiseKnotMultiplicity(index, multiplicity) {
const newKnotSequence = this.clone();
newKnotSequence.raiseKnotMultiplicityArrayMutSeq(index, multiplicity);
return newKnotSequence;
}
insertKnot(abscissae, multiplicity = 1) {
const newKnotSequence = this.clone();
newKnotSequence.insertKnotMutSeq(abscissae, multiplicity);
return newKnotSequence;
}
knotMultiplicityAtAbscissa(abcissa) {
let multiplicity = 0;
for (const knot of this.knotSequence) {
if (Math.abs(abcissa - knot.abscissa) < KnotSequences$1.KNOT_COINCIDENCE_TOLERANCE) {
multiplicity = knot.multiplicity;
}
}
if (multiplicity === 0) {
const warning = new ErrorLoging.WarningLog(this.constructor.name, "knotMultiplicityAtAbscissa", KnotSequences$2.WM_ABSCISSA_NOT_FOUND_IN_SEQUENCE);
warning.logMessage();
}
return multiplicity;
}
abscissaAtIndex(index) {
let abscissa = KnotSequences$1.UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA;
const multLastKnot = this.knotSequence[this.knotSequence.length - 1].multiplicity;
const indexPeriod = new KnotIndexIncreasingSequence.KnotIndexIncreasingSequence(index.knotIndex % (this.allAbscissae.length - multLastKnot));
let i = 0;
for (const knot of this) {
if (i === indexPeriod.knotIndex && knot !== undefined)
abscissa = knot;
i++;
}
return abscissa;
}
toKnotIndexStrictlyIncreasingSequence(index) {
const strictlyIncreasingKnotSequence = fromIncreasingPeriodicToStrictlyIncreasingPeriodicKnotSequence.fromIncreasingPeriodicToStrictlyIncreasingPeriodicKnotSequence(this);
const lastIdxStrictIncSeq = strictlyIncreasingKnotSequence.allAbscissae.length - 1;
const abscissa = this.abscissaAtIndex(index);
let i = 0;
for (const knot of strictlyIncreasingKnotSequence.allAbscissae) {
if (knot !== undefined) {
if (knot === abscissa)
break;
i++;
}
}
if (index.knotIndex > (this.allAbscissae.length - 1))
i = i + lastIdxStrictIncSeq;
return new KnotIndexStrictlyIncreasingSequence.KnotIndexStrictlyIncreasingSequence(i);
}
extractSubsetOfAbscissae(knotStart, knotEnd) {
let knots = [];
const sequence = this.allAbscissae.slice();
const lasIndex = this.allAbscissae.length - 1;
const multFirstKnot = this.knotSequence[0].multiplicity;
if (knotEnd.knotIndex <= knotStart.knotIndex) {
this.throwRangeErrorMessage("extractSubsetOfAbscissae", KnotSequences.EM_START_INDEX_OUTOF_RANGE);
}
if (knotStart.knotIndex > lasIndex) {
this.throwRangeErrorMessage("extractSubsetOfAbscissae", KnotSequences.EM_START_INDEX_GREATER_THAN_END_INDEX);
}
if ((knotEnd.knotIndex - knotStart.knotIndex) > (2 * lasIndex)) {
this.throwRangeErrorMessage("extractSubsetOfAbscissae", KnotSequences.EM_INDICES_SPAN_TWICE_PERIOD);
}
if (knotEnd.knotIndex > lasIndex) {
for (let i = multFirstKnot; i < this.allAbscissae.length; i++) {
sequence.push(this.allAbscissae[i] + this.allAbscissae[lasIndex]);
}
}
if (knotEnd.knotIndex >= (2 * lasIndex)) {
for (let i = multFirstKnot; i < this.allAbscissae.length; i++) {
sequence.push(this.allAbscissae[i] + 2 * this.allAbscissae[lasIndex]);
}
}
knots = sequence.slice(knotStart.knotIndex, knotEnd.knotIndex + 1);
return knots;
}
findSpan(u) {
let index = KnotSequences$1.UPPER_BOUND_NORMALIZED_BASIS_DEFAULT_ABSCISSA;
if (u > this.knotSequence[this.knotSequence.length - 1].abscissa) {
u = u % this.getPeriod();
}
if (u < KnotSequences$1.KNOT_SEQUENCE_ORIGIN) {
this.throwRangeErrorMessage("findSpan", KnotSequences.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) < KnotSequences$1.KNOT_COINCIDENCE_TOLERANCE) {
if (knot.abscissa === this.knotSequence[this.knotSequence.length - 1].abscissa) {
index -= this.knotSequence[this.knotSequence.length - 1].multiplicity;
}
index -= 1;
break;
}
}
return new KnotIndexIncreasingSequence.KnotIndexIncreasingSequence(index);
}
index = this.findSpanWithAbscissaDistinctFromKnotIncreasingKnotSequence(u);
}
return new KnotIndexIncreasingSequence.KnotIndexIncreasingSequence(index);
}
revertKnotSequence() {
const newKnotSequence = this.clone();
newKnotSequence.revertKnotSpacing();
return newKnotSequence;
}
decrementKnotMultiplicity(index) {
const newKnotSequence = this.clone();
newKnotSequence.decrementKnotMultiplicityMutSeq(index);
return newKnotSequence;
}
}
exports.IncreasingPeriodicKnotSequenceClosedCurve = IncreasingPeriodicKnotSequenceClosedCurve;