/** Set an attribute for the function * * @param attName :: The name of the attribute to set * @param att :: The attribute to set */ void BSpline::setAttribute(const std::string &attName, const API::IFunction::Attribute &att) { bool isUniform = attName == "Uniform" && att.asBool(); storeAttributeValue(attName, att); if (attName == "BreakPoints" || isUniform || attName == "StartX" || attName == "EndX") { resetKnots(); } else if (attName == "NBreak" || attName == "Order") { resetGSLObjects(); resetParameters(); resetKnots(); } }
/** * Recalculate the B-spline knots */ void BSpline::resetKnots() { bool isUniform = getAttribute("Uniform").asBool(); std::vector<double> breakPoints; if ( isUniform ) { // create uniform knots in the interval [StartX, EndX] double startX = getAttribute("StartX").asDouble(); double endX = getAttribute("EndX").asDouble(); gsl_bspline_knots_uniform( startX, endX, m_bsplineWorkspace.get() ); getGSLBreakPoints( breakPoints ); storeAttributeValue( "BreakPoints", Attribute(breakPoints) ); } else { // set the break points from BreakPoints vector attribute, update other attributes breakPoints = getAttribute( "BreakPoints" ).asVector(); // check that points are in ascending order double prev = breakPoints[0]; for(size_t i = 1; i < breakPoints.size(); ++i) { double next = breakPoints[i]; if ( next <= prev ) { throw std::invalid_argument("BreakPoints must be in ascending order."); } prev = next; } int nbreaks = getAttribute( "NBreak" ).asInt(); // if number of break points change do necessary updates if ( static_cast<size_t>(nbreaks) != breakPoints.size() ) { storeAttributeValue("NBreak", Attribute(static_cast<int>(breakPoints.size())) ); resetGSLObjects(); resetParameters(); } GSLVector bp = breakPoints; gsl_bspline_knots( bp.gsl(), m_bsplineWorkspace.get() ); storeAttributeValue( "StartX", Attribute(breakPoints.front()) ); storeAttributeValue( "EndX", Attribute(breakPoints.back()) ); } }