bSpline.h

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

Generated on Mon Jul 9 20:34:02 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2