// Insert knots and compute knot insertion matrix (to update control points) SparseMatrix BSplineBasis1D::insertKnots(double tau, unsigned int multiplicity) { if (!insideSupport(tau)) throw Exception("BSplineBasis1D::insertKnots: Cannot insert knot outside domain!"); if (knotMultiplicity(tau) + multiplicity > degree + 1) throw Exception("BSplineBasis1D::insertKnots: Knot multiplicity is too high!"); // New knot vector int index = indexHalfopenInterval(tau); std::vector<double> extKnots = knots; for (unsigned int i = 0; i < multiplicity; i++) extKnots.insert(extKnots.begin()+index+1, tau); if (!isKnotVectorRegular(extKnots)) throw Exception("BSplineBasis1D::insertKnots: New knot vector is not regular!"); // Return knot insertion matrix SparseMatrix A = buildKnotInsertionMatrix(extKnots); // Update knots knots = extKnots; return A; }
SparseMatrix BSplineBasis1D::refineKnotsLocally(double x) { if (!insideSupport(x)) throw Exception("BSplineBasis1D::refineKnotsLocally: Cannot refine outside support!"); if (getNumBasisFunctions() >= getNumBasisFunctionsTarget() || assertNear(knots.front(), knots.back())) { unsigned int n = getNumBasisFunctions(); DenseMatrix A = DenseMatrix::Identity(n,n); return A.sparseView(); } // Refined knot vector std::vector<double> refinedKnots = knots; auto upper = std::lower_bound(refinedKnots.begin(), refinedKnots.end(), x); // Check left boundary if (upper == refinedKnots.begin()) std::advance(upper, degree+1); // Get previous iterator auto lower = std::prev(upper); // Do not insert if upper and lower bounding knot are close if (assertNear(*upper, *lower)) { unsigned int n = getNumBasisFunctions(); DenseMatrix A = DenseMatrix::Identity(n,n); return A.sparseView(); } // Insert knot at x double insertVal = x; // Adjust x if it is on or close to a knot if (knotMultiplicity(x) > 0 || assertNear(*upper, x, 1e-6, 1e-6) || assertNear(*lower, x, 1e-6, 1e-6)) { insertVal = (*upper + *lower)/2.0; } // Insert new knot refinedKnots.insert(upper, insertVal); if (!isKnotVectorRegular(refinedKnots) || !isRefinement(refinedKnots)) throw Exception("BSplineBasis1D::refineKnotsLocally: New knot vector is not a proper refinement!"); // Build knot insertion matrix SparseMatrix A = buildKnotInsertionMatrix(refinedKnots); // Update knots knots = refinedKnots; return A; }
// Return indices of supporting basis functions at x std::vector<int> BSplineBasis1D::indexSupportedBasisfunctions(double x) const { std::vector<int> ret; if(insideSupport(x)) { int last = indexHalfopenInterval(x); if(last < 0) { last = knots.size() - 1 - (degree + 1); } int first = std::max((int)(last - degree), 0); for(int i = first; i <= last; i++) { ret.push_back(i); } } return ret; }
// Insert knots and compute knot insertion matrix (to update control points) bool BSplineBasis1D::insertKnots(SparseMatrix &A, double tau, unsigned int multiplicity) { if(!insideSupport(tau) || knotMultiplicity(tau) + multiplicity > degree + 1) return false; // New knot vector int index = indexHalfopenInterval(tau); std::vector<double> extKnots = knots; for(unsigned int i = 0; i < multiplicity; i++) extKnots.insert(extKnots.begin()+index+1, tau); assert(isKnotVectorRegular(extKnots)); // Return knot insertion matrix if(!buildKnotInsertionMatrix(A, extKnots)) return false; // Update knots knots = extKnots; return true; }