HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 override;
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  void reset() override;
67 
68  /// Return the type of the basis
69  GA_BASIS_TYPE getType() const override;
70 
71  /// Return the name of the basis
72  const char *getTypeName() const override;
73 
74  /// Return the dimension of the basis. For NURBS, this will be equivalent
75  /// to (getLength()-getOrder()).
76  int getDimension() const override;
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  bool getValidInterval(int &a, int &b) const override;
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  void evalInterval(fpreal u, int offset, int deriv,
104  fpreal64 *vals) const override;
105  void evalInterval(fpreal u, int offset,
106  int deriv, fpreal32 *vals) const override;
107 
108  /// Evaluate all the derivatives of the basis from 0 to deriv (inclusive).
109  void evalDerivativeMatrix(fpreal u, int offset, int deriv,
110  fpreal64 bmatx[][GA_MAXORDER]) const override;
112  int offset, int deriv,
113  fpreal32 bmatx[][GA_MAXORDER]) const override;
114 
115  /// Return the first valid segment. Returns -1 on an error.
116  int findStartOffset(fpreal u, int uoffset) const override;
117 
118  /// Compute one basis function (ie. the one with the given index)
119  /// value at u.
120  fpreal computeBValue(int index, fpreal u) const override;
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  int getBreakCount() const override;
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  int knotToBreakpoint(int &kidx, int a, int b) const override;
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.
149  fpreal tol=theBasisTolerance) const override;
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 override;
154 
155  /// Return the expected multiplicity of the end knots (1 by default):
156  int getEndMultiplicity() const override;
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  void getCvRangeOfDomain(int ustartidx, int ustopidx,
168  int &start_cv, int &end_cv) const override;
169  void getCvRangeOfDomain(fpreal ustart, fpreal ustop,
170  int &start_cv, int &end_cv) const override;
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  void getCvRangeOfBreakpoint(int bkp,
177  int &startcv, int &stopcv) const override;
178 
179  /// I/O functions for houdini9 format
180  bool saveH9(std::ostream &os, bool wrapped,
181  bool binary) const override;
182  bool loadH9(UT_IStream &is, int cvs, bool wrapped) override;
183 
184  /// Transitional method while we might need to import data from a GB_Basis.
185  /// Be careful calling this method as the order must be appropriate for the
186  /// number of knots.
187  /// TODO: Remove when no longer necessary.
188  bool import(int order, const UT_FloatArray &knots,
189  bool end_interpolation=true);
190 
191  /// Copy my data from the given source. If performing a compatible copy, we
192  /// only do the copy if if b has the same order and length as we do.
193  bool copyFrom(const GA_Basis &b, bool compatible=false) override;
194 
195  /// The validate() method will force the basis to be valid (if possible).
196  /// The adapt enum can be used to control the behaviour of this method.
197  bool validate(int adapt=GA_Basis::GA_BASIS_ADAPT_NONE) override;
198 
199  /// The checkValid() methods test to see whether th basis is valid given
200  /// a curve with
201  /// -# cvLen vertices
202  /// -# A basis length of bLen
203  /// -# Periodicity determined by doesWrap
204  bool checkValid(int cv_len, int b_len,
205  bool does_wrap) const override;
206 
207  /// Compute the idx'th greville abscissa of the domain vector. Clamping
208  /// to the valid interval is optional and might not make any difference
209  /// for some spline types.
210  fpreal getGreville(int idx, bool clamp=true,
211  bool wrap=false) const override;
212 
213  /// Grow the length of the basis by one, and set the value of the new entry
214  /// to last knot+1. The method returns the index of the appended element.
215  int grow(bool wrapped=false) override;
216 
217  /// Shrink the basis by one. The basis should not shrink beyond a valid
218  /// length. Return the new length.
219  int shrink(bool wrapped=false) override;
220 
221  /// Insert a new knot as a result of a CV insertion at index cvIdx. The
222  /// knot index is cvIdx + 1, which is returned by growAt() if all goes OK.
223  /// -1 is returned upon failure.
224  /// (NURBS basis only)
225  int growAt(unsigned cv_idx, bool wrapped);
226 
227  /// Delete a knot as a result of a CV removal at index cvIdx. The knot
228  /// index is cvIdx + 1. The method returns the new length if successful,
229  /// and -1 otherwise.
230  int shrinkAt(unsigned cv_idx, bool wrapped);
231 
232  /// Attach another basis to us and grow our basis as a result. The bases
233  /// must have the same type and order.
234  /// If "overlap" is true, we overlap the beginning of b with
235  /// our end.
236  /// Spreading makes sense when you can have multiple knots in the basis, and
237  /// causes identical knots to be spread within range of the neighbouring
238  /// knots.
239  bool attach(const GA_Basis &b, bool overlap=true,
240  bool spread=false) override;
241 
242  /// Change the size of the basis (and maybe some of its values too) to
243  /// make it a valid basis for wrapped splines.
244  void setWrapping(bool wrap) override;
245 
246  /// Change end interpolation
247  void setEndInterpolation(bool value, bool modify_knots);
248 
249  /// Reverse the breakpoints in the basis.
250  void reverse(bool wrapped) override;
251 
252  /// Find index in the knot vector for the break point corresponding to k.
253  int findOffset(fpreal k, int start_idx=0) const override;
254 
255  /// Create a new basis containing the partial merging of bases a and b
256  /// If their order is different return -1. Otherwise return 0.
257  /// The resultant basis contains knots a0..a1 of basis a merged with
258  /// knots b0..b1 from basis b (after being mapped onto a0..a1)
259  /// If the aknot or bknot array is given, they are set with the
260  /// (appropriately mapped) knots values corresponding to the new insertions
261  bool mergePartial(const GA_NUBBasis &a, const GA_NUBBasis &b,
262  int a0, int a1, int b0, int b1,
263  GA_KnotVector *aknots = nullptr,
264  GA_KnotVector *bknots = nullptr);
265 
266  /// Rebuild the basis as a uniform sequence with a given step.
267  void rebuild(fpreal ustart=0, fpreal ustep=1) override;
268 
269  /// Make the basis uniform of just find out if it is uniform:
270  void makeUniform(fpreal ustep=1) override;
271 
272  /// Reparameterize the basis using the chord-length method, and clamp it
273  /// to the valid interval. The origin and length of the valid domain remains
274  /// unchanged.
275  void chord(UT_Vector4Array &cvs) override;
276 
277  /// Slide the knots found in the given range left or right by an amount at
278  /// most as large as the distance to the nearest knot outside the range.
279  /// The bias is a percentage value of the left-right distance, its default
280  /// value is 0.5 (i.e. don't change anything), and is clamped to [0,1].
281  bool slideRange(fpreal umin, fpreal umax,
282  fpreal ubias=0.5) override;
283 
284  /// Cycle the knots, optionally keeping the original span length and origin.
285  bool cycle(int amount, bool keep_span);
286 
287  /// @{
288  /// Set up the knot vector with the given parameterization for the
289  /// approximiation.
290  void setKnotsByEqualSpacing(UT_Vector &param, bool wrapped=false);
291  void setKnotsByAveraging(UT_Vector &param, bool wrapped=false);
292  void setKnotsBySpreading(UT_Vector &param);
293  void setKnotsByBreakpoints(UT_Vector &param);
294  /// @}
295 
296  /// TODO: Public for GD_PrimNURBCurve use
297 
299  { setEndInterpolation(!myEndInterpolation, true); }
300  void makeNURBSPeriodic();
301 
302  // TODO: Public for IGES_EntityBSplineSurface use
303  void updateEndInterpolation();
304 
305  /// Return the amount of memory used
306  int64 getMemoryUsage(bool inclusive) const override
307  {
308  int64 mem = inclusive ? sizeof(*this) : 0;
309  mem += GA_Basis::getMemoryUsage(false);
310  return mem;
311  }
312 
313  /// Test whether the basis is a uniform basis.
314  bool isUniform() const;
315 
316 private:
317  void initialize(fpreal start, fpreal step,
318  int length, int order, bool interp);
319 
320  int findNURBSStart(fpreal k, int start=0) const;
321  int findNURBSValidStart(fpreal u, int off=-1) const;
322  void initializeNURBS(fpreal first, fpreal step);
323  void spreadNURBSKnots(int ai, int bi);
324 
325  // NUB basis interpolation end condition
326  bool myEndInterpolation;
327 };
328 
329 #endif
GLint first
Definition: glcorearb.h:405
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
GLenum clamp
Definition: glcorearb.h:1234
int64 getMemoryUsage(bool inclusive) const override
Return the amount of memory used.
Definition: GA_NUBBasis.h:306
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:475
const GLuint GLenum const void * binary
Definition: glcorearb.h:1924
virtual int getBreakpoints(GA_KnotVector &a, fpreal tol=theBasisTolerance) const =0
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
#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:14
virtual bool slideRange(fpreal umin, fpreal umax, fpreal ubias=0.5)=0
float fpreal32
Definition: SYS_Types.h:200
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
double fpreal64
Definition: SYS_Types.h:201
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
virtual bool checkValid(int cvLen, int bLen, bool doesWrap) const =0
GLintptr offset
Definition: glcorearb.h:665
virtual int knotToBreakpoint(int &kidx, int a, int b) const =0
virtual GA_BASIS_TYPE getType() const =0
Return the type of the basis.
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
GLdouble GLdouble GLint GLint order
Definition: glad.h:2676
long long int64
Definition: SYS_Types.h:116
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 native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
Definition: logging.h:294
virtual bool validate(int adapt=GA_Basis::GA_BASIS_ADAPT_NONE)=0
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
virtual void chord(UT_Vector4Array &cvs)=0
GLdouble t
Definition: glad.h:2397
virtual bool attach(const GA_Basis &b, bool overlap=true, bool spread=false)=0
GLenum GLfloat param
Definition: glcorearb.h:104
virtual bool loadH9(UT_IStream &is, int cvs, bool wrapped)=0
fpreal64 fpreal
Definition: SYS_Types.h:277
GA_BASIS_TYPE
Definition: GA_Basis.h:33
GLuint index
Definition: glcorearb.h:786
void toggleEndInterpolation()
TODO: Public for GD_PrimNURBCurve use.
Definition: GA_NUBBasis.h:298
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
Definition: core.h:1131
virtual const char * getTypeName() const =0
Return the name of the basis.
GLboolean r
Definition: glcorearb.h:1222
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
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).
virtual bool isEqual(const GA_Basis &basis) const =0
Compare to see whether the basis is equal.
GLenum src
Definition: glcorearb.h:1793
int findValidStart(fpreal u, int uoffset=-1) const
Definition: GA_NUBBasis.h:91