bool BSplineBasis1D::refineKnots(SparseMatrix &A) { // Build refine knot vector std::vector<double> refinedKnots = knots; unsigned int targetNumKnots = targetNumBasisfunctions + degree + 1; while(refinedKnots.size() < targetNumKnots) { int index = indexLongestInterval(refinedKnots); double newKnot = (refinedKnots.at(index) + refinedKnots.at(index+1))/2.0; refinedKnots.insert(lower_bound(refinedKnots.begin(), refinedKnots.end(), newKnot), newKnot); } assert(isKnotVectorRegular(refinedKnots) && isRefinement(refinedKnots)); // Return knot insertion matrix if(!buildKnotInsertionMatrix(A, refinedKnots)) { return false; } // Update knots knots = refinedKnots; return true; }
SparseMatrix BSplineBasis1D::decomposeToBezierForm() { // Build refine knot vector std::vector<double> refinedKnots = knots; // Start at first knot and add knots until all knots have multiplicity degree + 1 std::vector<double>::iterator knoti = refinedKnots.begin(); while (knoti != refinedKnots.end()) { // Insert new knots int mult = degree + 1 - knotMultiplicity(*knoti); if (mult > 0) { std::vector<double> newKnots(mult, *knoti); refinedKnots.insert(knoti, newKnots.begin(), newKnots.end()); } // Advance to next knot knoti = std::upper_bound(refinedKnots.begin(), refinedKnots.end(), *knoti); } if (!isKnotVectorRegular(refinedKnots) || !isRefinement(refinedKnots)) throw Exception("BSplineBasis1D::refineKnots: New knot vector is not a proper refinement!"); // Return knot insertion matrix SparseMatrix A = buildKnotInsertionMatrix(refinedKnots); // Update knots knots = refinedKnots; return A; }
// 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; }
// 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; }
SparseMatrix BSplineBasis1D::refineKnots() { // Build refine knot vector std::vector<double> refinedKnots = knots; unsigned int targetNumKnots = targetNumBasisfunctions + degree + 1; while (refinedKnots.size() < targetNumKnots) { int index = indexLongestInterval(refinedKnots); double newKnot = (refinedKnots.at(index) + refinedKnots.at(index+1))/2.0; refinedKnots.insert(std::lower_bound(refinedKnots.begin(), refinedKnots.end(), newKnot), newKnot); } if (!isKnotVectorRegular(refinedKnots) || !isRefinement(refinedKnots)) throw Exception("BSplineBasis1D::refineKnots: New knot vector is not a proper refinement!"); // Return knot insertion matrix SparseMatrix A = buildKnotInsertionMatrix(refinedKnots); // Update knots knots = refinedKnots; return A; }