Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
NurbsBase.hh
1 /*
2  * NurbsBase.hh
3  *
4  * Created on: Jul 1, 2010
5  * Author: jordt
6  */
7 
8 #ifndef NURBSBASE_HH_
9 #define NURBSBASE_HH_
10 
11 #include <vector>
12 
13 //The following switches are meant to be for debuging and experimenting:
14 
15 // Evaluate the nurbs recursivly according to their mathematical
16 // definition (very slow)
17 //#define NURBS_BASE_RECURSIVE_EVALUATION
18 
19 // This switch makes the evaluation a little slower but thread safe.
20 // To avoid this draw back call the BaseFunc with an additional Cache
21 // pointer (This is fast and thread safe)
22 #define NURBS_BASE_THREAD_SAFE
23 
24 namespace BIAS{
25 
26  /** Base class for NURBS classes. The NURBS Base function is implemented here
27  * @author jordt
28  */
29  class NurbsBase {
30  public:
31 
32  /** Standard Constructor
33  * @param knotsPerDim The number of knots in the knot vector (without the dublications)
34  * @param degree The degree of the b-splines
35  * @param dimension The dimension of the parameter space! (not the control point space)
36  */
37  NurbsBase(int knotsPerDim = 4, int degree = 2, int dimension = 1);
38 
39  /// Empty Destructor (Virtual to make this whole thing polymorphic)
41 
42  /// Returns the number of knots of the NURBS
43  int GetNumKnots() const;
44 
45  /// Returns the degree of the NURBS
46  int GetDegree() const;
47 
48  /// Returns the number of control points per dimension
49  int GetNumCtrlPts() const;
50 
51  /// Returns the position of a knot with a given index
52  /// of a given dimension.
53  double GetKnot(int dim, int index) const;
54 
55  /// Set the position of a knot with a given index and
56  /// of a given dimension
57  void SetKnot(int dim, int index, double value);
58 
59  protected:
60 
61  /// The vector of knot vectors (One for each dimension)
62  std::vector<std::vector<double> > knotVector_;
63 
64  /// Number of knots in each dimension
66 
67  /// Degree of the b-splines
68  int degree_;
69 
70  /// The number of control points per dimension
72 
73  #ifndef NURBS_BASE_THREAD_SAFE
74  /// The function value cache for the serial evaluation
75  std::vector<double> evalCache_;
76  #endif //NURBS_BASE_THREAD_SAFE
77 
78  int baseOps_;
79 
80  #ifdef NURBS_BASE_RECURSIVE_EVALUATION
81  /// This is standard implementation of the recursive nurbs evaluation.
82  inline double BaseFunc(const int &dim,const int &knot,const int &degree,const double &u) const{
83  if (degree == 0){
84  if (u < knotVector_[dim][knot]) return 0.0;
85  if (u > knotVector_[dim][knot+1]) return 0.0;
86  if (u == knotVector_[dim][knot+1] && u != 1.0) return 0.0;
87  return 1.0;
88  }
89 
90  double recursiveA = 0.0;
91  if (knotVector_[dim][knot+degree] != knotVector_[dim][knot])
92  recursiveA = (u - knotVector_[dim][knot]) / (knotVector_[dim][knot+degree]-knotVector_[dim][knot]) * BaseFunc(dim,knot,degree - 1,u);
93 
94  double recursiveB = 0.0;
95  if (knotVector_[dim][knot+degree+1] != knotVector_[dim][knot+1])
96  recursiveB = (knotVector_[dim][knot+degree+1]-u) / (knotVector_[dim][knot+degree+1]-knotVector_[dim][knot+1]) * BaseFunc(dim,knot+1,degree - 1,u);
97 
98  return recursiveA + recursiveB;
99  }
100  #else //NURBS_BASE_RECURSIVE_EVALUATION
101  /** This is a serial implementation of the recursive nurbs evaluation.
102  * Recursive function values are stored in the evaluation cache (evalCache_)
103  * @param dim The dimension (determines which knot vector is used)
104  * @param knot The index of the knot in the knot vector
105  * @param degree The current degree the function is evaluated in
106  * @param u The parmeter for which the base function is evaluated */
107 
108  inline double BaseFunc(const int &dim, const int &knot, const int &degree, const double &u) const{
109 
110  #ifdef NURBS_BASE_THREAD_SAFE
111  double* evalCache_ = new double[degree+1];
112  #endif
113 
114  // baseOps: The number of function calls on this level of recursion.
115  int baseOps = degree+1;
116  for(int k = 0; k < baseOps; k++)
117  evalCache_[k] = (u < knotVector_[dim][knot+k] || u > knotVector_[dim][knot+k+1] || (u == knotVector_[dim][knot+k+1] && u!=1.0) ? 0.0 : 1.0);
118 
119  // After computing the deepest recursion level, the levels based on the cache values are rendered:
120  for(int level = 1; level <= degree; level++){
121  baseOps = baseOps -1;
122  for(int k = 0; k < baseOps; k++){
123  evalCache_[k] =
124  ((knotVector_[dim][knot+level+k] == knotVector_[dim][knot+k]) ? 0.0 :(u - knotVector_[dim][knot+k]) / (knotVector_[dim][knot+level+k]-knotVector_[dim][knot+k]) * evalCache_[k])
125  +
126  ((knotVector_[dim][knot+level+1+k] == knotVector_[dim][knot+1+k]) ? 0.0 :(knotVector_[dim][knot+level+1+k]-u) / (knotVector_[dim][knot+level+1+k]-knotVector_[dim][knot+1+k]) * evalCache_[k+1]);
127  }
128  }
129 
130  // The result then lies in the first cache array element:
131  #ifdef NURBS_BASE_THREAD_SAFE
132  double returnValue = evalCache_[0];
133  delete[] evalCache_;
134  return returnValue;
135  #else
136  return evalCache_[0];
137  #endif
138 
139  }
140  #endif //NURBS_BASE_RECURSIVE_EVALUATION
141 
142 
143  /** This is a serial implementation of the recursive nurbs evaluation.
144  * Recursive function values are stored in the evaluation cache (evalCache_)
145  * In this function, the cache pointer has to be provided in order to save the
146  * memory allocation time.
147  * @param dim The dimension (determines which knot vector is used)
148  * @param knot The index of the knot in the knot vector
149  * @param degree The current degree the function is evaluated in
150  * @param u The parmeter for which the base function is evaluated
151  * @param cachePointer The pointer to a cache, this function is allowed to use (already allocated). The size should be degree+1*/
152  inline double BaseFunc(const int &dim, const int &knot, const int &degree, const double &u, double* &cachePointer) const{
153 
154  // baseOps: The number of function calls on this level of recursion.
155  int baseOps = degree+1;
156  for(int k = 0; k < baseOps; k++)
157  cachePointer[k] = (u < knotVector_[dim][knot+k] || u > knotVector_[dim][knot+k+1] || (u == knotVector_[dim][knot+k+1] && u!=1.0)? 0.0 : 1.0);
158 
159  // After computing the deepest recursion level, the levels based on the cache values are rendered:
160  for(int level = 1; level <= degree; level++){
161  baseOps = baseOps -1;
162  for(int k = 0; k < baseOps; k++){
163  cachePointer[k] =
164  ((knotVector_[dim][knot+level+k] == knotVector_[dim][knot+k]) ? 0.0 :(u - knotVector_[dim][knot+k]) / (knotVector_[dim][knot+level+k]-knotVector_[dim][knot+k]) * cachePointer[k])
165  +
166  ((knotVector_[dim][knot+level+1+k] == knotVector_[dim][knot+1+k]) ? 0.0 :(knotVector_[dim][knot+level+1+k]-u) / (knotVector_[dim][knot+level+1+k]-knotVector_[dim][knot+1+k]) * cachePointer[k+1]);
167  }
168  }
169 
170  // The result then lies in the first cache array element:
171  return cachePointer[0];
172  }
173 
174  };
175 
176 }
177 
178 #endif /* NURBSBASE_HH_ */
double GetKnot(int dim, int index) const
Returns the position of a knot with a given index of a given dimension.
Definition: NurbsBase.cpp:69
int degree_
Degree of the b-splines.
Definition: NurbsBase.hh:68
int knotsPerDim_
Number of knots in each dimension.
Definition: NurbsBase.hh:65
double BaseFunc(const int &dim, const int &knot, const int &degree, const double &u) const
This is a serial implementation of the recursive nurbs evaluation.
Definition: NurbsBase.hh:108
NurbsBase(int knotsPerDim=4, int degree=2, int dimension=1)
Standard Constructor.
Definition: NurbsBase.cpp:16
void SetKnot(int dim, int index, double value)
Set the position of a knot with a given index and of a given dimension.
Definition: NurbsBase.cpp:75
double BaseFunc(const int &dim, const int &knot, const int &degree, const double &u, double *&cachePointer) const
This is a serial implementation of the recursive nurbs evaluation.
Definition: NurbsBase.hh:152
Base class for NURBS classes.
Definition: NurbsBase.hh:29
std::vector< std::vector< double > > knotVector_
The vector of knot vectors (One for each dimension)
Definition: NurbsBase.hh:62
int GetNumCtrlPts() const
Returns the number of control points per dimension.
Definition: NurbsBase.cpp:65
int GetNumKnots() const
Returns the number of knots of the NURBS.
Definition: NurbsBase.cpp:57
~NurbsBase()
Empty Destructor (Virtual to make this whole thing polymorphic)
Definition: NurbsBase.hh:40
int numCtrlPoints_
The number of control points per dimension.
Definition: NurbsBase.hh:71
int GetDegree() const
Returns the degree of the NURBS.
Definition: NurbsBase.cpp:61