HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GA_NUBBasis.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GA_NUBBasis.h ( GA Library, C++)
7  *
8  * COMMENTS: Stores an array of knots for a NURBS patch
9  */
10 
11 #pragma once
12 
13 #ifndef __GA_NUBBasis__
14 #define __GA_NUBBasis__
15 
16 #include "GA_API.h"
17 #include "GA_Basis.h"
18 #include "GA_Defines.h"
19 #include "GA_KnotVector.h"
20 
21 #include <UT/UT_VectorTypes.h>
22 #include <SYS/SYS_Types.h>
23 
24 #include <iosfwd>
25 
26 
27 class UT_IStream;
28 
29 template<typename T> class UT_VectorT;
31 
32 
33 /// Knot scale factor for unclamping end interpolating curves/surfaces.
34 #define GA_NUB_UNCLAMP_SCALE 3.0
35 
36 
37 /// @brief NURBS basis classes which maintain knot vectors
38 ///
39 /// The GA_NUBBasis class maintains the knot vectors for NURBS.
40 /// The basis consists of:
41 /// -# The order of the basis (degree+1)
42 /// -# The knot vector (an array of doubles)
43 /// -# A flag for end interpolation
44 class GA_API GA_NUBBasis : public GA_Basis
45 {
46 public:
47  /// The default constructor will choose length/order based on the defaults
48  /// for the basis type.
49  /// default: order=4, length=8
50  GA_NUBBasis(int length=-1, int order=-1, bool end_interpolation=true);
51  GA_NUBBasis(fpreal start, fpreal step, int length, int order=-1, bool end_interpolation=true);
52  // This c-tor allows you to build the equivalent of a Bezier basis.
53  // To end up with a Bezier-like basis, set the multiplicity=ord-1.
54  // The end points will always have 'ord' multiplicity, so this is
55  // an end-interpolating basis. The multiplicity must be >= 1 and < ord.
56  GA_NUBBasis(int bkpoints, int multiplicity, int ord);
57  GA_NUBBasis(const GA_NUBBasis &src);
58 
59  /// Test to see if two bases are equal
60  bool isEqual(const GA_Basis &basis) const;
61  bool operator==(const GA_NUBBasis &a) const;
62  bool operator!=(const GA_NUBBasis &a) const
63  { return !(*this == a); }
64 
65  /// Re-initializes the basis to default values
66  virtual void reset();
67 
68  /// Return the type of the basis
69  virtual GA_BASIS_TYPE getType() const;
70 
71  /// Return the name of the basis
72  virtual const char *getTypeName() const;
73 
74  /// Return the dimension of the basis. For NURBS, this will be equivalent
75  /// to (getLength()-getOrder()).
76  virtual int getDimension() const;
77 
78  /// Return the end-interpolation flag
79  bool getEndInterpolation() const
80  { return myEndInterpolation; }
81 
82  /// Get the boundaries of the valid evaluation interval (as indices)
83  virtual bool getValidInterval(int &a, int &b) const;
84 
85  /// Return the index of the knot where the valid evaluation begins.
86  /// Typically, for a cubic spline, this index is 3 in the end-point
87  /// interpolating case and 1 otherwise. If u is completely outside
88  /// the valid knot sequence, this method returns -1.
89  ///
90  /// Equivalent to findStartOffset(u, uoffset).
91  int findValidStart(fpreal u, int uoffset = -1) const
92  { return findNURBSValidStart(u, uoffset); }
93 
94  /// Return the index in the knot vector such that knotVec[idx] <= k and
95  /// k < knotVec[idx+1]. If k is less than the first valid knot, return
96  /// -1, and if k is greater than the last valid knot, return the index
97  /// of the last valid knot (i.e. the dimension).
98  int findStart(fpreal k, int start_idx = 0) const
99  { return findNURBSStart(k, start_idx); }
100 
101  /// Evaluate on a specific domain interval, on which at least one
102  /// basis function is non-zero given domain point u.
103  virtual void evalInterval(fpreal u, int offset, int deriv,
104  fpreal64 *vals) const;
105  virtual void evalInterval(fpreal u, int offset,
106  int deriv, fpreal32 *vals) const;
107 
108  /// Evaluate all the derivatives of the basis from 0 to deriv (inclusive).
109  virtual void evalDerivativeMatrix(fpreal u, int offset, int deriv,
110  fpreal64 bmatx[][GA_MAXORDER]) const;
111  virtual void evalDerivativeMatrix(fpreal u,
112  int offset, int deriv,
113  fpreal32 bmatx[][GA_MAXORDER]) const;
114 
115  /// Return the first valid segment. Returns -1 on an error.
116  virtual int findStartOffset(fpreal u, int uoffset) const;
117 
118  /// Compute one basis function (ie. the one with the given index)
119  /// value at u.
120  virtual fpreal computeBValue(int index, fpreal u) const;
121 
122  /// Find out if two knot sequences are similar (ie if the knot spacings
123  /// are the same all over) and their knot count is the same.
124  bool isSimilar(const GA_NUBBasis &b) const;
125 
126  /// Return the number of breakpoints (ie. unique knots) in the knot
127  /// vector, in the valid interval.
128  virtual int getBreakCount() const;
129 
130  /// @{
131  /// Find the index of the last knot in the sequence that defines the given
132  /// breakpoint, or the breakpoint of the domain value. Returns -1 if not
133  /// found.
134  /// @note The search is done within the limits of the valid interval.
135  int findBreakpoint(int idx) const;
136  int findBreakpoint(fpreal t) const;
137  /// @}
138 
139  /// Given the index of a knot (kidx) and two bounds in the knot sequence
140  /// (a and b) find out the index of the breakpoint that the knot represents,
141  /// and possibly adjust kidx so that knot[kidx+1] > knot[kidx]. Return -1
142  /// if not found.
143  virtual int knotToBreakpoint(int &kidx, int a, int b) const;
144 
145  /// Compute an array of breakpoints (i.e. unique knots) in the valid
146  /// interval and return their number. The tolerance is used to
147  /// differentiate between close knots.
148  virtual int getBreakpoints(GA_KnotVector &a,
149  fpreal tol=theBasisTolerance) const;
150 
151  /// Return the multiplicity of a domain point or -1 if outside the domain.
152  /// "uidx" is the index of the largest breakpoint <= u.
153  int getMultiplicity(fpreal u, int &uidx) const;
154 
155  /// Return the expected multiplicity of the end knots (1 by default):
156  virtual int getEndMultiplicity() const;
157 
158  /// Change the multiplicity of the knot by inserting it "r" times WITHOUT
159  /// checking its current multiplicity. kidx is the index of a knot t such
160  /// that k >= t.
161  void refine(fpreal k, int kidx, int r, bool wrapped);
162 
163  /// Given a domain range in the valid interval, compute the range of CVs
164  /// that will be involved in the evaluation of the curve in that range.
165  /// Since the basis doesn't know about wrapping, the endcv index might
166  /// be higher than the spline's number of CVs.
167  virtual void getCvRangeOfDomain(int ustartidx, int ustopidx,
168  int &start_cv, int &end_cv) const;
169  virtual void getCvRangeOfDomain(fpreal ustart, fpreal ustop,
170  int &start_cv, int &end_cv) const;
171 
172  /// Given valid breakpoint index, compute the range of CVs that have a
173  /// non-zero influence at the knot of the breakpoint. Since the basis
174  /// doesn't know about wrapping, the endcv index might be higher than the
175  /// spline's number of CVs.
176  virtual void getCvRangeOfBreakpoint(int bkp,
177  int &startcv, int &stopcv) const;
178 
179  /// I/O functions for houdini9 format
180  virtual bool saveH9(std::ostream &os, bool wrapped, bool binary) const;
181  virtual bool loadH9(UT_IStream &is, int cvs, bool wrapped);
182 
183  /// Transitional method while we might need to import data from a GB_Basis.
184  /// Be careful calling this method as the order must be appropriate for the
185  /// number of knots.
186  /// TODO: Remove when no longer necessary.
187  bool import(int order, const UT_FloatArray &knots,
188  bool end_interpolation=true);
189 
190  /// Copy my data from the given source. If performing a compatible copy, we
191  /// only do the copy if if b has the same order and length as we do.
192  virtual bool copyFrom(const GA_Basis &b, bool compatible=false);
193 
194  /// The validate() method will force the basis to be valid (if possible).
195  /// The adapt enum can be used to control the behaviour of this method.
196  virtual bool validate(int adapt=GA_Basis::GA_BASIS_ADAPT_NONE);
197 
198  /// The checkValid() methods test to see whether th basis is valid given
199  /// a curve with
200  /// -# cvLen vertices
201  /// -# A basis length of bLen
202  /// -# Periodicity determined by doesWrap
203  virtual bool checkValid(int cvLen, int bLen, bool doesWrap) const;
204 
205  /// Compute the idx'th greville abscissa of the domain vector. Clamping
206  /// to the valid interval is optional and might not make any difference
207  /// for some spline types.
208  virtual fpreal getGreville(int idx, bool clamp=true,
209  bool wrap=false) const;
210 
211  /// Grow the length of the basis by one, and set the value of the new entry
212  /// to last knot+1. The method returns the index of the appended element.
213  virtual int grow(bool wrapped=false);
214 
215  /// Shrink the basis by one. The basis should not shrink beyond a valid
216  /// length. Return the new length.
217  virtual int shrink(bool wrapped=false);
218 
219  /// Insert a new knot as a result of a CV insertion at index cvIdx. The
220  /// knot index is cvIdx + 1, which is returned by growAt() if all goes OK.
221  /// -1 is returned upon failure.
222  /// (NURBS basis only)
223  int growAt(unsigned cvIdx, bool wrapped);
224 
225  /// Delete a knot as a result of a CV removal at index cvIdx. The knot
226  /// index is cvIdx + 1. The method returns the new length if successful,
227  /// and -1 otherwise.
228  int shrinkAt(unsigned cvIdx, bool wrapped);
229 
230  /// Attach another basis to us and grow our basis as a result. The bases
231  /// must have the same type and order.
232  /// If "overlap" is true, we overlap the beginning of b with
233  /// our end.
234  /// Spreading makes sense when you can have multiple knots in the basis, and
235  /// causes identical knots to be spread within range of the neighbouring
236  /// knots.
237  virtual bool attach(const GA_Basis &b, bool overlap=true,
238  bool spread=false);
239 
240  /// Change the size of the basis (and maybe some of its values too) to
241  /// make it a valid basis for wrapped splines.
242  virtual void setWrapping(bool wrap);
243 
244  /// Change end interpolation
245  void setEndInterpolation(bool value, bool modify_knots);
246 
247  /// Reverse the breakpoints in the basis.
248  virtual void reverse(bool wrapped);
249 
250  /// Find index in the knot vector for the break point corresponding to k.
251  virtual int findOffset(fpreal k, int startIdx=0) const;
252 
253  /// Create a new basis containing the partial merging of bases a and b
254  /// If their order is different return -1. Otherwise return 0.
255  /// The resultant basis contains knots a0..a1 of basis a merged with
256  /// knots b0..b1 from basis b (after being mapped onto a0..a1)
257  /// If the aknot or bknot array is given, they are set with the
258  /// (appropriately mapped) knots values corresponding to the new insertions
259  bool mergePartial(const GA_NUBBasis &a, const GA_NUBBasis &b,
260  int a0, int a1, int b0, int b1,
261  GA_KnotVector *aknots = 0,
262  GA_KnotVector *bknots = 0);
263 
264  /// Rebuild the basis as a uniform sequence with a given step.
265  virtual void rebuild(fpreal ustart=0, fpreal ustep=1);
266 
267  /// Make the basis uniform of just find out if it is uniform:
268  virtual void makeUniform(fpreal ustep=1);
269 
270  /// Reparameterize the basis using the chord-length method, and clamp it
271  /// to the valid interval. The origin and length of the valid domain remains
272  /// unchanged.
273  virtual void chord(UT_Vector4Array &cvs);
274 
275  /// Slide the knots found in the given range left or right by an amount at
276  /// most as large as the distance to the nearest knot outside the range.
277  /// The bias is a percentage value of the left-right distance, its default
278  /// value is 0.5 (i.e. don't change anything), and is clamped to [0,1].
279  virtual bool slideRange(fpreal umin, fpreal umax,
280  fpreal ubias=0.5);
281 
282  /// Cycle the knots, optionally keeping the original span length and origin.
283  bool cycle(int amount, bool keepSpan);
284 
285  /// @{
286  /// Set up the knot vector with the given parameterization for the
287  /// approximiation.
288  void setKnotsByEqualSpacing(UT_Vector &param, bool wrapped=false);
289  void setKnotsByAveraging(UT_Vector &param, bool wrapped=false);
290  void setKnotsBySpreading(UT_Vector &param);
291  void setKnotsByBreakpoints(UT_Vector &param);
292  /// @}
293 
294  /// TODO: Public for GD_PrimNURBCurve use
295 
297  { setEndInterpolation(!myEndInterpolation, true); }
298  void makeNURBSPeriodic();
299 
300  // TODO: Public for IGES_EntityBSplineSurface use
301  void updateEndInterpolation();
302 
303  /// Return the amount of memory used
304  virtual int64 getMemoryUsage(bool inclusive) const
305  {
306  int64 mem = inclusive ? sizeof(*this) : 0;
307  mem += GA_Basis::getMemoryUsage(false);
308  return mem;
309  }
310 
311  /// Test whether the basis is a uniform basis.
312  bool isUniform() const;
313 
314 private:
315  void initialize(fpreal start, fpreal step,
316  int length, int order, bool interp);
317 
318  int findNURBSStart(fpreal k, int start=0) const;
319  int findNURBSValidStart(fpreal u, int off=-1) const;
320  void initializeNURBS(fpreal first, fpreal step);
321  void spreadNURBSKnots(int ai, int bi);
322 
323  // NUB basis interpolation end condition
324  bool myEndInterpolation;
325 };
326 
327 #endif
GLint first
Definition: glcorearb.h:404
virtual int shrink(bool wrapped=false)=0
UT_VectorT< fpreal64 > UT_Vector
Definition: GA_NUBBasis.h:29
virtual void makeUniform(fpreal ustep=1)=0
Make the basis uniform of just find out if it is uniform:
virtual fpreal getGreville(int idx, bool clamp=true, bool wrap=false) const =0
virtual int getMultiplicity(fpreal u, int &uidx) const =0
virtual int findOffset(fpreal k, int startIdx=0) const =0
Find index in the knot vector for the break point corresponding to k.
GLuint start
Definition: glcorearb.h:474
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
virtual int getBreakpoints(GA_KnotVector &a, fpreal tol=theBasisTolerance) const =0
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
#define GA_MAXORDER
Definition: GA_Defines.h:17
virtual void evalInterval(fpreal u, int offset, int deriv, fpreal64 *vals) const =0
virtual fpreal computeBValue(int index, fpreal u) const =0
#define GA_API
Definition: GA_API.h:12
virtual bool slideRange(fpreal umin, fpreal umax, fpreal ubias=0.5)=0
virtual int findStartOffset(fpreal u, int uoffset) const =0
virtual int getBreakCount() const =0
virtual void reset()=0
Re-initializes the basis to default values.
bool operator!=(const GA_NUBBasis &a) const
Definition: GA_NUBBasis.h:62
virtual bool copyFrom(const GA_Basis &b, bool compatible=false)
virtual int grow(bool wrapped=false)=0
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
long long int64
Definition: SYS_Types.h:100
virtual bool checkValid(int cvLen, int bLen, bool doesWrap) const =0
virtual int knotToBreakpoint(int &kidx, int a, int b) const =0
virtual int64 getMemoryUsage(bool inclusive) const
Return the amount of memory used.
Definition: GA_NUBBasis.h:304
double fpreal64
Definition: SYS_Types.h:185
virtual GA_BASIS_TYPE getType() const =0
Return the type of the basis.
GLintptr offset
Definition: glcorearb.h:664
Bezier or NURBS basis classes which maintain knot vectors.
Definition: GA_Basis.h:49
NURBS basis classes which maintain knot vectors.
Definition: GA_NUBBasis.h:44
virtual int64 getMemoryUsage(bool inclusive) const
Return the amount of memory used.
Definition: GA_Basis.h:379
virtual void setWrapping(bool wrap)=0
virtual int getDimension() const =0
virtual void rebuild(fpreal ustart=0, fpreal ustep=1)=0
Rebuild the basis as a uniform sequence with a given step.
OPENVDB_API void initialize()
Global registration of basic types.
Definition: logging.h:316
virtual bool validate(int adapt=GA_Basis::GA_BASIS_ADAPT_NONE)=0
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
virtual void chord(UT_Vector4Array &cvs)=0
virtual bool attach(const GA_Basis &b, bool overlap=true, bool spread=false)=0
GLsizei const GLfloat * value
Definition: glcorearb.h:823
double fpreal
Definition: SYS_Types.h:263
GLenum GLfloat param
Definition: glcorearb.h:103
virtual bool loadH9(UT_IStream &is, int cvs, bool wrapped)=0
GA_BASIS_TYPE
Definition: GA_Basis.h:33
GLuint index
Definition: glcorearb.h:785
void toggleEndInterpolation()
TODO: Public for GD_PrimNURBCurve use.
Definition: GA_NUBBasis.h:296
virtual bool saveH9(std::ostream &os, bool wrapped, bool binary) const =0
I/O functions for houdini9 format.
int findStart(fpreal k, int start_idx=0) const
Definition: GA_NUBBasis.h:98
virtual const char * getTypeName() const =0
Return the name of the basis.
GLboolean r
Definition: glcorearb.h:1221
virtual void reverse(bool wrapped)=0
Reverse the breakpoints in the basis.
bool getEndInterpolation() const
Return the end-interpolation flag.
Definition: GA_NUBBasis.h:79
float fpreal32
Definition: SYS_Types.h:184
virtual int getEndMultiplicity() const
Return the expected multiplicity of the end knots (1 by default):
virtual void getCvRangeOfDomain(int ustartidx, int ustopidx, int &start_cv, int &end_cv) const =0
virtual void getCvRangeOfBreakpoint(int bkp, int &startcv, int &stopcv) const =0
virtual bool getValidInterval(int &a, int &b) const =0
Get the boundaries of the valid evaluation interval (as indices)
virtual void evalDerivativeMatrix(fpreal u, int offset, int deriv, fpreal64 bmatx[][GA_MAXORDER]) const =0
Evaluate all the derivatives of the basis from 0 to deriv (inclusive).
GLenum clamp
Definition: glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:794
virtual bool isEqual(const GA_Basis &basis) const =0
Compare to see whether the basis is equal.
GLenum src
Definition: glcorearb.h:1792
int findValidStart(fpreal u, int uoffset=-1) const
Definition: GA_NUBBasis.h:91