bSpline.h

Go to the documentation of this file.
00001 
00015 #ifndef DLR_NUMERIC_BSPLINE_H
00016 #define DLR_NUMERIC_BSPLINE_H
00017 
00018 #include <vector>
00019 #include <dlrNumeric/array1D.h>
00020 #include <dlrNumeric/array2D.h>
00021 #include <dlrNumeric/polynomial.h>
00022 
00023 namespace dlr {
00024 
00025   namespace numeric {
00026 
00047     template <class Type>
00048     class BSpline {
00049     public:
00050 
00063       BSpline(size_t order=2, bool isPeriodic=true);
00064 
00065 
00071       BSpline(const BSpline& other);
00072 
00073 
00087       double
00088       getMaximumSValue();
00089 
00090 
00103       double
00104       getMinimumSValue();
00105       
00106 
00117       void
00118       setControlPoints(const std::vector<Type>& controlPoints);
00119 
00120 
00139       void
00140       setKnotMultiplicities(const std::vector<size_t>& knotMultiplicities);
00141 
00142 
00169       void
00170       setNumberOfNodes(size_t numberOfNodes,
00171                        bool setKnotMultiplicitiesFlag=true);
00172       
00173 
00206       void
00207       setNumberOfNodes(size_t numberOfNodes,
00208                        const std::vector<double>& nodePositions,
00209                        bool setKnotMultiplicitiesFlag=true);
00210       
00211 
00212       
00218       BSpline<Type>&
00219       operator=(const BSpline<Type>& other);
00220 
00221       
00228       Type
00229       operator()(double sValue);
00230       
00231 
00232     protected:
00233 
00259       Polynomial<double>
00260       computeBasisFunction(size_t order,
00261                            size_t spanNumber,
00262                            size_t componentNumber,
00263                            const Array1D<size_t>& cumulativeKnotCounts,
00264                            const Array1D<double>& knotPositions);
00265 
00266       
00289       Array1D< Array1D<double> >
00290       getControlPointVectors(size_t order,
00291                              size_t numberOfNodes,
00292                              const Array1D<size_t>& cumulativeKnotCounts,
00293                              const std::vector<Type>& controlPoints);
00294 
00295       
00325       Array1D< Array2D<double> >
00326       getCoefficientMatrices(size_t order,
00327                              size_t numberOfNodes,
00328                              const Array1D<double>& nodePositions,
00329                              const Array1D<double>& knotPositions,
00330                              const Array1D<size_t>& cumulativeKnotCounts);
00331 
00332 
00346       double
00347       getKnotPosition(int knotNumber,
00348                       const Array1D<double>& knotPositions);
00349 
00350 
00360       size_t
00361       getSpanNumber(double sValue);
00362       
00363 
00371       void
00372       setNodePositions(const std::vector<double>& nodePositions);
00373 
00374 
00375       Array1D< Array2D<double> > m_coefficientMatrixArray;
00376       std::vector<Type> m_controlPoints;
00377       Array1D< Array1D<Type> > m_controlPointVectorArray;
00378       Array1D<size_t> m_cumulativeKnotCounts;
00379       Array1D<double> m_inputVector;
00380       bool m_isPeriodic;
00381       bool m_isUniform;
00382       Array1D<double> m_knotPositionArray;
00383       Array1D<double> m_nodePositionArray;
00384       size_t m_numberOfNodes;
00385       size_t m_order;
00386       size_t m_orderPlusOne;
00387     };
00388 
00389 
00390   } // namespace numeric
00391   
00392 } // namespace dlr
00393 
00394 
00395 /* =============================================================== */
00396 /* Implementation follows.                                         */
00397 /* =============================================================== */
00398 
00399 
00400 #include <cmath>
00401 #include <dlrNumeric/functional.h>
00402 #include <dlrNumeric/utilities.h>
00403 
00404 namespace dlr {
00405 
00406   namespace numeric {
00407 
00408     // xxx remove m_numberOfNodes?
00409 
00410     // This constructor builds a BSpline instance of unspecified length.
00411     template <class Type>
00412     BSpline<Type>::
00413     BSpline(size_t order, bool isPeriodic)
00414       : m_coefficientMatrixArray(),
00415         m_controlPoints(),
00416         m_controlPointVectorArray(),
00417         m_cumulativeKnotCounts(),
00418         m_inputVector(order + 1),
00419         m_isPeriodic(isPeriodic),
00420         m_isUniform(true),
00421         m_knotPositionArray(),
00422         m_nodePositionArray(),
00423         m_numberOfNodes(0),
00424         m_order(order),
00425         m_orderPlusOne(order + 1)
00426     {
00427       // Empty
00428     }
00429 
00430     
00431     // The copy constructor does a deep copy.
00432     template <class Type>
00433     BSpline<Type>::
00434     BSpline(const BSpline& other)
00435       : m_coefficientMatrixArray(other.m_coefficientMatrixArray.copy()),
00436         m_controlPoints(other.m_controlPoints),
00437         m_controlPointVectorArray(other.m_controlPointVectorArray.copy()),
00438         m_cumulativeKnotCounts(other.m_cumulativeKnotCounts.copy()),
00439         m_inputVector(other.m_inputVector.copy()),
00440         m_isPeriodic(other.isPeriodic),
00441         m_isUniform(other.isUniform),
00442         m_knotPositionArray(other.m_knotPositionArray.copy()),
00443         m_nodePositionArray(other.m_nodePositionArray.copy()),
00444         m_numberOfNodes(other.m_numberOfNodes),
00445         m_order(other.m_order),
00446         m_orderPlusOne(other.m_orderPlusOne)
00447     {
00448       // Empty
00449     }
00450       
00451 
00452 
00453     
00454     // This member function returns the maximum value for the spline
00455     // parameter S.
00456     template <class Type>
00457     double
00458     BSpline<Type>::
00459     getMaximumSValue()
00460     {
00461       if(m_nodePositionArray.size() == 0) {
00462         DLR_THROW(StateException, "BSpline::getMaximumSValue()",
00463                   "Node positions have not been set.  You must first call"
00464                   " setNumberOfNodes() or setNodePositions().");
00465       }
00466       return m_nodePositionArray[m_nodePositionArray.size() - 1];
00467     }
00468 
00469 
00470     // This member function returns the minimum value for the spline
00471     // parameter S.
00472     template <class Type>
00473     double
00474     BSpline<Type>::
00475     getMinimumSValue()
00476     {
00477       if(m_nodePositionArray.size() == 0) {
00478         DLR_THROW(StateException, "BSpline::getMinimumSValue()",
00479                   "Node positions have not been set.  You must first call"
00480                   " setNumberOfNodes() or setNodePositions().");
00481       }
00482       return m_nodePositionArray[0];
00483     }
00484 
00485 
00486     // This member function sets the values of the control points of
00487     // the spline.
00488     template <class Type>
00489     void
00490     BSpline<Type>::
00491     setControlPoints(const std::vector<Type>& controlPoints)
00492     {
00493       if(m_isPeriodic) {
00494         if(controlPoints.size() != m_numberOfNodes - 1) {
00495           std::ostringstream message;
00496           message << "Argument controlPoints has " << controlPoints.size()
00497                   << " elements, but should have " << m_numberOfNodes - 1
00498                   << " elements for a periodic " << m_numberOfNodes
00499                   << " node spline because the first and last nodes overlap.";
00500           DLR_THROW(ValueException, "BSpline::setControlPoints()",
00501                     message.str().c_str());
00502         }
00503       } else {
00504         if(controlPoints.size() != m_numberOfNodes) {
00505           std::ostringstream message;
00506           message << "Argument controlPoints has " << controlPoints.size()
00507                   << " elements, but should have " << m_numberOfNodes
00508                   << " elements for a non-periodic " << m_numberOfNodes
00509                   << " node spline.";
00510           DLR_THROW(ValueException, "BSpline::setControlPoints()",
00511                     message.str().c_str());
00512         }
00513       }
00514       if(m_knotPositionArray.size() < m_nodePositionArray.size()) {
00515         DLR_THROW(StateException, "BSpline::setControlPoints()",
00516                   "Knot positions have not been initialized.  You must first"
00517                   " call setKnotMultiplicies(), or else call"
00518                   " setNumberOfNodes() with argument setKnotMultipliciesFlag"
00519                   " set to true.");
00520       }
00521       m_controlPoints = controlPoints;
00522       m_controlPointVectorArray = this->getControlPointVectors(
00523         m_order, m_numberOfNodes, m_cumulativeKnotCounts, controlPoints);
00524     }
00525 
00526     
00527     // This member function sets the knot multiplicity at each node
00528     // of the spline.
00529     template <class Type>
00530     void
00531     BSpline<Type>::
00532     setKnotMultiplicities(const std::vector<size_t>& knotMultiplicities)
00533     {
00534       if(knotMultiplicities.size() != m_numberOfNodes) {
00535         std::ostringstream message;
00536         message << "Argument knotMultiplicities has "
00537                 << knotMultiplicities.size() << " elements, when a(n) "
00538                 << m_numberOfNodes << " element vector was expected.";
00539         DLR_THROW(ValueException, "BSpline::setKnotMultiplicities()",
00540                   message.str().c_str());
00541       }
00542       if(m_isPeriodic) {
00543         if(knotMultiplicities[0] != knotMultiplicities[m_numberOfNodes - 1]) {
00544           std::ostringstream message;
00545           message << "For a periodic spline, first and last node are actually "
00546                   << "the same and so must have the same knot multiplicity, "
00547                   << "but knotMultiplicities[0] = " << knotMultiplicities[0]
00548                   << " and knotMultiplicities[" << m_numberOfNodes - 1
00549                   << "] = " << knotMultiplicities[m_numberOfNodes - 1] << ".";
00550           DLR_THROW(ValueException, "BSpline::setKnotMultiplicities()",
00551                     message.str().c_str());
00552         }
00553       } else {
00554         if(knotMultiplicities[0] != m_order
00555            || knotMultiplicities[m_numberOfNodes - 1] != m_order) {
00556           std::ostringstream message;
00557           message << "For a non-periodic spline of order " << m_order << ", "
00558                   << "first and last knot must have multiplicity " << m_order
00559                   << ", but knotMultiplicities[0] = " << knotMultiplicities[0]
00560                   << " and knotMultiplicities[" << m_numberOfNodes - 1
00561                   << "] = " << knotMultiplicities[m_numberOfNodes - 1] << ".";
00562           DLR_THROW(ValueException, "BSpline::setKnotMultiplicities()",
00563                     message.str().c_str());
00564         }
00565       }
00566       if(m_cumulativeKnotCounts.size() != knotMultiplicities.size()) {
00567         m_cumulativeKnotCounts.reinit(knotMultiplicities.size());
00568       }
00569       std::partial_sum(knotMultiplicities.begin(), knotMultiplicities.end(),
00570                        m_cumulativeKnotCounts.begin());
00571       size_t numberOfKnots = m_cumulativeKnotCounts[m_numberOfNodes - 1];
00572       if(m_knotPositionArray.size() != numberOfKnots) {
00573         m_knotPositionArray.reinit(numberOfKnots);
00574       }
00575       size_t knotIndex = 0;
00576       for(size_t nodeIndex = 0; nodeIndex < m_numberOfNodes; ++nodeIndex) {
00577         while(knotIndex < m_cumulativeKnotCounts[nodeIndex]) {
00578           m_knotPositionArray[knotIndex] = m_nodePositionArray[nodeIndex];
00579           ++knotIndex;
00580         }
00581       }
00582       m_coefficientMatrixArray = this->getCoefficientMatrices(
00583         m_order, m_numberOfNodes, m_nodePositionArray, m_knotPositionArray,
00584         m_cumulativeKnotCounts);
00585     }
00586 
00587 
00588     
00589     // This member function both specifies the number of nodes in
00590     // the spline and sets the node positions so that the spline is
00591     // "uniform".
00592     template <class Type>
00593     void
00594     BSpline<Type>::
00595     setNumberOfNodes(size_t numberOfNodes, bool setKnotMultiplicitiesFlag)
00596     {
00597       std::vector<double> nodePositions(numberOfNodes);
00598       for(size_t index0 = 0; index0 < numberOfNodes; ++index0) {
00599         nodePositions[index0] = static_cast<double>(index0);
00600       }
00601       this->setNumberOfNodes(
00602         numberOfNodes, nodePositions, setKnotMultiplicitiesFlag);
00603       m_isUniform = true;
00604     }
00605 
00606 
00607     // This member function specifies the number of nodes in the
00608     // spline and allows the user to set the position of each node.
00609     template <class Type>
00610     void
00611     BSpline<Type>::
00612     setNumberOfNodes(size_t numberOfNodes,
00613                      const std::vector<double>& nodePositions,
00614                      bool setKnotMultiplicitiesFlag)
00615     {
00616       m_numberOfNodes = numberOfNodes;
00617       m_isUniform = false;
00618       this->setNodePositions(nodePositions);
00619       if(setKnotMultiplicitiesFlag) {
00620         std::vector<size_t> knotMultiplicities(numberOfNodes, size_t(1));
00621         if(!m_isPeriodic) {
00622           knotMultiplicities[0] = m_order + 1;
00623           knotMultiplicities[numberOfNodes - 1] = m_order + 1;
00624         }
00625         this->setKnotMultiplicities(knotMultiplicities);
00626       }
00627     }
00628 
00629 
00630     // The assigment operator does a deep copy.
00631     template <class Type>
00632     BSpline<Type>&
00633     BSpline<Type>::
00634     operator=(const BSpline<Type>& other)
00635     {
00636       if(&other != this) {
00637         m_coefficientMatrixArray = other.m_coefficientMatrixArray.copy();
00638         m_controlPoints = other.m_controlPoints;
00639         m_controlPointVectorArray = other.m_controlPointVectorArray.copy();
00640         m_cumulativeKnotCounts = other.m_cumulativeKnotCounts.copy();
00641         m_inputVector = other.m_inputVector.copy();
00642         m_isPeriodic = other.isPeriodic;
00643         m_isUniform = other.isUniform;
00644         m_knotPositionArray = other.m_knotPositionArray.copy();
00645         m_nodePositionArray = other.m_nodePositionArray.copy();
00646         m_numberOfNodes = other.m_numberOfNodes;
00647         m_order = other.m_order;
00648         m_orderPlusOne = other.m_orderPlusOn;
00649       }
00650     }
00651 
00652     
00653     // This operator evaluates the spline at the specified value of
00654     // spline parameter s.
00655     template <class Type>
00656     Type
00657     BSpline<Type>::
00658     operator()(double sValue)
00659     {
00660       // Construct a vector of powers of s.
00661       double accumulator = 1.0;
00662       m_inputVector[0] = accumulator;
00663       for(size_t index0 = 1; index0 < m_inputVector.size(); ++index0) {
00664         accumulator *= sValue;
00665         m_inputVector[index0] = accumulator;
00666       }
00667 
00668       // Select the appropriate coefficients and control points for
00669       // the span to which sValue belongs.
00670       size_t spanNumber = this->getSpanNumber(sValue);
00671       const Array1D<Type>& controlPointVector =
00672         m_controlPointVectorArray[spanNumber];
00673       const Array2D<double>& coefficientMatrix =
00674         m_coefficientMatrixArray[spanNumber];
00675 
00676 
00677       // Actually compute the polynomial values and multiply by
00678       // control points.
00679       Type result = (dot(coefficientMatrix.row(0), m_inputVector)
00680                      * controlPointVector[0]);
00681       for(size_t index1 = 1; index1 < m_orderPlusOne; ++index1) {
00682         result += (dot(coefficientMatrix.row(index1), m_inputVector)
00683                    * controlPointVector[index1]);
00684       }
00685       return result;
00686     }
00687 
00688     
00689     // This protected member function computes one spline basis
00690     // function for use in calculating spline values.
00691     template <class Type>
00692     Polynomial<double>
00693     BSpline<Type>::
00694     computeBasisFunction(size_t order,
00695                          size_t spanNumber,
00696                          size_t componentNumber,
00697                          const Array1D<size_t>& cumulativeKnotCounts,
00698                          const Array1D<double>& knotPositions)
00699     {
00700       // Initialize 0-order basis functions according to the rule:
00701       //
00702       //   B_(n,1)(s) = 1     if k_n <= s < k_(n+1)
00703       //   B_(n,1)(s) = 0     otherwise
00704       //
00705       // Where B_(n,1)(s) is the 0-order basis function with support
00706       // (k_n <= s < k_(n+1), k_n is the position of the n^th knot in
00707       // the spline, k_(n+1) is the position of the (n+1)^st knot in
00708       // the spline, and s is the parametric distance along the
00709       // spline.
00710       // 
00711       // Note that only one of the 0 order components is non-zero at
00712       // any given point along the spline.  The next three lines
00713       // create an array of order + 1 polynomials, initialize all of
00714       // them to zero, and then set the appropriate polynomial to one.
00715       Array1D< Polynomial<double> > componentArray(order + 1);
00716       componentArray = Polynomial<double>(0.0);
00717       componentArray[order - componentNumber] = Polynomial<double>(1.0);
00718 
00719       // Recursively compute higher order polynomials accoring to the rule:
00720       //
00721       //  B_(n,d)(s) = ((s - k_n)B_(n,d-1)(s)/(k_(n+d-1) - k_n)
00722       //                + (k_(n+d) - s)B_(n+1,d-1)(s)/(k_(n+d) - k_(n+1)))
00723       //
00724       // For each stage of the recursion.
00725       for(int orderIndex = 1; orderIndex <= static_cast<int>(order); ++orderIndex) {
00726 
00727         // Polynomials of the next higher order will be put into
00728         // newComponentArray.
00729         Array1D< Polynomial<double> > newComponentArray(
00730           componentArray.size() - 1);
00731 
00732         // For each element of newComponentArray.
00733         for(size_t subComponentIndex = 0;
00734             subComponentIndex < newComponentArray.size();
00735             ++subComponentIndex) {
00736           // knotNumber is the number of the first (lowest numbered)
00737           // knot in the recursion rule.  knotNumber corresponds to
00738           // "n" in the equation above.
00739           int knotNumber =
00740             (static_cast<int>(cumulativeKnotCounts[spanNumber]) - 1
00741              - static_cast<int>(m_order)
00742              + static_cast<int>(componentNumber)
00743              + static_cast<int>(subComponentIndex));
00744           double k_n =
00745             this->getKnotPosition(knotNumber, knotPositions);
00746           double k_nPlus1 =
00747             this->getKnotPosition(knotNumber + 1, knotPositions);
00748           double k_nPlusDMinus1 =
00749             this->getKnotPosition(knotNumber + orderIndex, knotPositions);
00750           double k_nPlusD =
00751             this->getKnotPosition(knotNumber + orderIndex + 1, knotPositions);
00752           double span0 = k_nPlusDMinus1 - k_n;
00753           double span1 = k_nPlusD - k_nPlus1;
00754           Polynomial<double> scaleFunction0(1.0 / span0, -k_n / span0);
00755           Polynomial<double> scaleFunction1(-1.0 / span1, k_nPlusD / span1);
00756           newComponentArray[subComponentIndex] = (
00757             scaleFunction0 * componentArray[subComponentIndex]
00758             + scaleFunction1 * componentArray[subComponentIndex + 1]);
00759         }
00760         // Now that the recursive rule has been carried out for this
00761         // level, (this value of "d" in the equation above), we can
00762         // forget the previous level and get ready to recurse.
00763         componentArray = newComponentArray;
00764       }
00765       if(componentArray.size() != 1) {
00766         DLR_THROW(LogicException, "BSpline::computeBasisFunction()",
00767                   "Recursion terminated incorrectly.");
00768       }
00769       return componentArray[0];
00770     }
00771 
00772 
00773     // This protected member function returns an array in which each
00774     // element corresponds to one span of the spline, and contains a
00775     // matrix of the polynomial coefficients of the basis functions
00776     // that affect the spline values within that span.  This
00777     template <class Type>
00778     Array1D< Array2D<double> >
00779     BSpline<Type>::
00780     getCoefficientMatrices(size_t order,
00781                            size_t numberOfNodes,
00782                            const Array1D<double>& nodePositions,
00783                            const Array1D<double>& knotPositions,
00784                            const Array1D<size_t>& cumulativeKnotCounts)
00785     {
00786       size_t numberOfSpans = numberOfNodes - 1;
00787       Array1D< Array2D<double> > coefficientMatrixArray(numberOfSpans);
00788       for(size_t spanNumber = 0; spanNumber < numberOfSpans; ++spanNumber) {
00789         coefficientMatrixArray[spanNumber] =
00790           Array2D<double>(order + 1, order + 1);
00791 
00792         for(size_t componentIndex = 0; componentIndex < order + 1;
00793             ++componentIndex) {
00794           Polynomial<double> basisFunction = this->computeBasisFunction(
00795             order, spanNumber, componentIndex, cumulativeKnotCounts,
00796             knotPositions);
00797           if(basisFunction.getOrder() != order) {
00798             DLR_THROW(LogicException, "BSpline::getCoefficientMatrices()",
00799                       "Basis function has incorrect order.");
00800           }
00801           coefficientMatrixArray[spanNumber].row(componentIndex).copy(
00802             basisFunction.getCoefficientArray());
00803         }
00804       }
00805       return coefficientMatrixArray;
00806     }
00807     
00808 
00809     // This protected member function returns an array in which each
00810     // element corresponds to one span of the spline, and contains
00811     // the control-point values that affect the spline values
00812     // within that span.  This function is used to allow efficient
00813     template <class Type>
00814     Array1D< Array1D<double> >
00815     BSpline<Type>::
00816     getControlPointVectors(size_t order, size_t numberOfNodes,
00817                            const Array1D<size_t>& cumulativeKnotCounts,
00818                            const std::vector<Type>& controlPoints)
00819     {
00820       size_t numberOfSpans = numberOfNodes - 1;
00821       size_t numberOfBasisFunctions = order + 1;
00822       size_t numberOfKnots;
00823       if(m_isPeriodic) {
00824         numberOfKnots = cumulativeKnotCounts[numberOfNodes - 2];
00825       } else {
00826         numberOfKnots = cumulativeKnotCounts[numberOfNodes - 1];
00827       }
00828       Array1D< Array1D<Type> > controlPointVectorArray(numberOfSpans);
00829       for(size_t spanNumber = 0; spanNumber < numberOfSpans; ++spanNumber) {
00830         Array1D<Type> newVector(numberOfBasisFunctions);
00831         int knotIndex =
00832           static_cast<int>(cumulativeKnotCounts[spanNumber]) 
00833                   - static_cast<int>(numberOfBasisFunctions);
00834         for(size_t controlPointIndex = 0;
00835             controlPointIndex < newVector.size();
00836             ++controlPointIndex) {
00837           if(knotIndex < 0) {
00838             newVector[controlPointIndex] =
00839               controlPoints[numberOfKnots + knotIndex];
00840           } else if(knotIndex >= static_cast<int>(numberOfKnots)) {
00841             newVector[controlPointIndex] =
00842               controlPoints[knotIndex - numberOfKnots];
00843           } else {
00844             newVector[controlPointIndex] = controlPoints[knotIndex];
00845           }
00846           ++knotIndex;
00847         }
00848         controlPointVectorArray[spanNumber] = newVector;
00849       }
00850       return controlPointVectorArray;
00851     }
00852 
00853 
00854     // This protected member function wraps argument knotNumber so
00855     // that it is in the range [0, knotPositions.size() - 1], and then
00856     // returns the corresponding value from knotPositions.
00857     template <class Type>
00858     double
00859     BSpline<Type>::
00860     getKnotPosition(int knotNumber,
00861                     const Array1D<double>& knotPositions)
00862     {
00863       if(knotNumber < 0) {
00864         int wrappedIndex =
00865           static_cast<int>(knotPositions.size()) - 1 + knotNumber;
00866         double offsetDistance = (knotPositions[knotPositions.size() - 1]
00867                                  - knotPositions[wrappedIndex]);
00868         return knotPositions[0] - offsetDistance;
00869       } else if(knotNumber >= static_cast<int>(knotPositions.size())) {
00870         int wrappedIndex =
00871           knotNumber - static_cast<int>(knotPositions.size()) + 1;
00872         double offsetDistance = (knotPositions[wrappedIndex]
00873                                  - knotPositions[0]);
00874         return knotPositions[knotPositions.size() - 1] + offsetDistance;
00875       } 
00876       return knotPositions[knotNumber];
00877     }
00878 
00879     
00880     // This protected member function returns the number of the span
00881     // in which the specified spline parameter value lies.
00882     template <class Type>
00883     size_t
00884     BSpline<Type>::
00885     getSpanNumber(double sValue)
00886     {
00887       size_t returnValue;
00888       if(m_isUniform) {
00889         int maximumSpanNumber = static_cast<int>(m_numberOfNodes) - 1;
00890         int spanNumber = int(floor(sValue));
00891         if(m_isPeriodic) {
00892           while(spanNumber < 0) {
00893             spanNumber += maximumSpanNumber;
00894           }
00895           while(spanNumber >= maximumSpanNumber) {
00896             spanNumber -= maximumSpanNumber;
00897           }
00898         } else {
00899           if((spanNumber < 0) || (spanNumber >= maximumSpanNumber)) {
00900             DLR_THROW(ValueException, "BSpline::getSpanNumber()",
00901                       "Argument sValue is out of range.");
00902           }
00903         }
00904         returnValue = static_cast<size_t>(spanNumber);
00905       } else { // if(m_isUniform)
00906         double maximumSValue = m_nodePositionArray[m_numberOfNodes - 1];
00907         double minimumSValue = m_nodePositionArray[0];
00908         if(m_isPeriodic) {
00909           while(sValue < minimumSValue) {
00910             sValue += (maximumSValue - minimumSValue);
00911           }
00912           while(sValue >= maximumSValue) {
00913             sValue -= (maximumSValue - minimumSValue);
00914           }
00915         } else {
00916           if((sValue < minimumSValue) || (sValue >= maximumSValue)) {
00917             DLR_THROW(ValueException, "BSpline::getSpanNumber()",
00918                       "Argument sValue is out of range.");
00919           }
00920         }
00921         Array1D<double>::const_iterator nodeIterator = std::upper_bound(
00922           m_nodePositionArray.begin(), m_nodePositionArray.end(), sValue);
00923         returnValue =
00924           static_cast<size_t>(nodeIterator - m_nodePositionArray.begin());
00925       }
00926       return returnValue;
00927     }
00928       
00929 
00930     // This protected member function sets the positions of the
00931     // nodes in the spline.
00932     template <class Type>
00933     void
00934     BSpline<Type>::
00935     setNodePositions(const std::vector<double>& nodePositions)
00936     {
00937       if(nodePositions.size() != m_numberOfNodes) {
00938         std::ostringstream message;
00939         message << "Argument nodePositions has "
00940                 << nodePositions.size() << " elements, when a(n) "
00941                 << m_numberOfNodes << " element vector was expected.";
00942         DLR_THROW(ValueException, "BSpline::setNodePositions()",
00943                   message.str().c_str());
00944       }
00945       if(m_nodePositionArray.size() != nodePositions.size()) {
00946         m_nodePositionArray.reinit(nodePositions.size());
00947       }
00948       std::copy(nodePositions.begin(), nodePositions.end(),
00949                 m_nodePositionArray.begin());
00950     }
00951 
00952     
00953   } // namespace numeric
00954 
00955 } // namespace dlr
00956 
00957 #endif /* #ifndef DLR_NUMERIC_BSPLINE_H */

Generated on Wed Nov 25 00:42:41 2009 for dlrUtilities Utility Library by  doxygen 1.5.8