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; }
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; }
bool BSplineBasis1D::buildKnotInsertionMatrix(SparseMatrix &A, const std::vector<double> &refinedKnots) const { if (!isRefinement(refinedKnots)) { throw Exception("BSplineBasis1D::buildKnotInsertionMatrix: New knot vector is not a proper refinement of the old!"); } std::vector<double> knotsAug = refinedKnots; unsigned int n = knots.size() - degree - 1; unsigned int m = knotsAug.size() - degree - 1; //SparseMatrix A(m,n); A.resize(m,n); A.reserve(Eigen::VectorXi::Constant(n,degree+1)); // Build A row-by-row for(unsigned int i = 0; i < m; i++) { int u = indexHalfopenInterval(knotsAug.at(i)); // Assuming that p > 0 SparseMatrix R(1,1); R.insert(0,0) = 1; for(unsigned int j = 1; j <= degree; j++) { SparseMatrix Ri = buildBasisMatrix(knotsAug.at(i+j), u, j); R = R*Ri; } // Size check if(R.rows() != 1 || R.cols() != degree+1) { throw Exception("BSplineBasis1D::buildKnotInsertionMatrix: Incorrect matrix dimensions!"); } // Insert row values int j = u-degree; // First insertion index for(int k = 0; k < R.outerSize(); ++k) for(SparseMatrix::InnerIterator it(R,k); it; ++it) { A.insert(i,j+it.col()) = it.value(); } } A.makeCompressed(); 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; }