HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GEO_PrimNURBCurve.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: Geometry Library (C++)
7  *
8  * COMMENTS:
9  * This class implements a non-uniform B-Spline curve defined by
10  * a set of knots, basis function, and CVs.
11  *
12  */
13 
14 #pragma once
15 
16 #ifndef __GEO_PrimNURBCurve_h__
17 #define __GEO_PrimNURBCurve_h__
18 
19 #include "GEO_API.h"
20 #include "GEO_Curve.h"
21 #include "GEO_PrimType.h"
22 #include <UT/UT_Array.h>
23 
24 class GA_Detail;
25 class GA_NUBBasis;
26 
28 {
29 public:
30  using GEO_Face::refine;
31 
32 protected:
33  /// NOTE: The constructor should only be called from subclass
34  /// constructors.
36  : GEO_Curve(d, offset)
37  {}
38 
39  /// NOTE: The destructor should only be called from subclass
40  /// destructors.
41  /// Please read the comments on the parent class destructor.
42  ~GEO_PrimNURBCurve() override {}
43 
44 public:
45  /// Increases div to the first valid number of divisions, given
46  /// the order and closed flag. For NURBs, this is a straightforward
47  /// minimum.
48  /// Returns true if the divisions changed.
49  static bool forceValidDivisions(int &div, int order, bool closed);
50 
51  // Given a domain value (u), store all the basis derivatives (from 0 to du
52  // inclusive) into bmatx. Return the min index of the CVs needed
53  // for the linear combination. The indices may exceed the number of
54  // vertices if the curve is wrapped, so remember to use % getVertexCount().
55  int evaluateBasisDerivs(float u, float bmatx[][GA_MAXORDER],
56  int &cvoffset, unsigned du = 0,
57  int uoffset = -1) const override;
58 
59  // Evaluate the basis at the given point in the domain and also return
60  // the index of the first CV to linearly combine the basis with. The CV
61  // index may exceed the number of vertices if the curve is wrapped,
62  // so remember to use modulus (%). This method handles both rational and
63  // non-rational curves.
64  int evaluateBasis(float u,float *ubvals, int &cvoffset,
65  unsigned du=0, int uoffset=-1) const override;
66 
67  // Compute the location of the breakpoint. Return 0 if OK, else -1.
68  int evaluateBreakpoint(int uidx, UT_Vector4 &pos,
69  int du=0) const override;
70 
71  // compute the un-normalized lengths corresponding to points on the curve
72  // evaluated at the valid knots parameter values
73  // (ones with which lie within curve paramer domain) and store them
74  // in the 'lengths' array. Returns the curve "length" (same as last knot).
75  // The meaning of "length" depends on ptype, and can mean chord length,
76  // square chord length, approximate arc length.
78  UT_FloatArray &lengths) const override;
79 
80  // Given a CV index figure out the min/max indicies of the knots between
81  // which the curve needs to be re-evaluated if the CV changes. If not
82  // given a valid CV index, the method returns -1. Otherwise it returns 0.
83  // If the curve wraps the domain we return will be rather large.
84  int domainRangeOfCV(int cvidx, int &mink,int &maxk) const override;
85 
86  // Given a CV index figure out the min/max breakpoints which are
87  // affected if the CV changes. If not given a valid CV index, the
88  // method returns -1. Otherwise it returns 0. Also returns -1 if
89  // no breakpoints are affected.
90  // NOTE: use % breakCount since maxbkp may be >= breakCount
91  int breakpointRangeOfCV(int cvidx, int &minbkp,
92  int &maxbkp) const override;
93 
94  // Reparameterize the curve by changing its basis. Everything up and
95  // including the first valid knot remains unchanged. This type of
96  // reparameterization is generally NOT shape preserving:
97  void reparameterize(GA_ParameterizationType ptype) override;
98 
99  // Warp the curve at u by the given delta. Change 1 or 2 Cvs and possibly
100  // insert a knot once or more as well. If a knot is inserted or we happen
101  // to land exactly on a knot, we change only one CV. The bias makes sense
102  // only when changing 2 CVs, and will be ignored altogether if < 0.
103  // We return the index of the affected knot in the sequence, or -1 if
104  // there's an error.
105  int warp(float u, const UT_Vector3 &delta,
106  GA_AttributeRefMap &map,
107  float sharpness = 0.0f, float bias = -1.0f) override;
108 
109  // Translate the CVs such that the given breakpoint change positions by
110  // the given delta. Return -1 if something goes wrong, 0 if translation
111  // was successful.
112  // NOTE: uindices cannot contain any duplicates. If the curve is closed,
113  // the first and last breakpoint are considered the same.
114  int translateBreakpoints(const UT_IntArray &uindices,
115  const UT_Vector3 &delta,
116  int fixbkpts = 1,
117  GA_PointGroup *ptgroup = NULL,
118  GEO_Delta *geodelta = 0) override;
119  int transformBreakpoints(const UT_IntArray &uindices,
120  const UT_Matrix4 &matx,
121  int fixbkpts = 1,
122  GA_PointGroup *ptgroup = NULL,
123  GEO_Delta *geodelta = 0) override;
124 
125  // Append another face to us in one of two ways: blend the two endpoints
126  // or connect them straight or rounded. The bias ranges from 0 to 1 and is
127  // relevant only to blending. The tolerance for blending: if 0, the two
128  // endpoints will merge into one point with a discontinuity; if less than
129  // 1, we insert knots into the curves to minimize the affected areas; if 1,
130  // no refinement is done. For the non-blend case, the tolerance will
131  // generate a span whose shape goes from round to straight; 0 tolerance
132  // means straight connection. If unrefine is on, we'll try to reduce the
133  // complexity of the face if we're connecting rounded. We return 0 if OK
134  // and -1 if error. Both curves must be open, clamped, and have the same
135  // order.
136  int attach(const GEO_Face &face,
137  int blend = 1,
138  float bias = 0.5f,
139  float tolerance = 1.0f,
140  int unrefine = 1,
141  GA_PointGroup *ptgroup=0) override;
142 
143  // Build a planar (domain) face of the same type as us and with the same
144  // number of vertices. Copying the (x,y) values of our points to the planar
145  // face is optional.
146  GD_Face *planar(GD_Detail &dgdp, int copyxy = 0) const override;
147 
148  // Set the wrap or open flag, and make sure the basis knot vectors are
149  // consistent with the change. These functions are virtual by inheritance.
150 
151  // Convert a topologically open curve into a topologically closed one.
152  // The rounded flag is mainly for surface end caps to indicate a half cap
153  // or a full cap.
154  //
155  // If rounded = 1:
156  // closed rounded curve.
157  // non end interpolated.
158  // may or may not preserve shape depending on the flag.
159  // (however, always preserve shape if original curve is
160  // non end interpolated)
161  // If rounded = 0:
162  // closed curve with a straight edge.
163  // end interpolated.
164  // always preserve the shape. (ignore preserveShape flag)
165  void close(int rounded = 1, int preserveShape = 0) override;
166 
167  // Convert a topologically closed curve into a topologically open one.
168  //
169  // For an end interpolation closed curve, we get (topologically) open
170  // curve:
171  // 1. For preserve shape:
172  // exactly the same shape without any open gap.
173  // end interpolated open curve.
174  // 2. For non preserve shape:
175  // hull remained but the curve changed shape with an open gap.
176  // end interpolated open curve.
177  //
178  // For a non end interpolation closed curve, we get (topologically) open
179  // curve:
180  // 1. For preserve shape:
181  // a portion of the original curve, thus have open gap.
182  // non end interpolated open curve.
183  // 2. For non preserve shape:
184  // hull remained but the curve changed shape with an open gap.
185  // Note: end interpolated open curve.
186  void open(int preserveShape = 0, int = 0) override;
187 
188  // Check if the basis interpolates the endpoints, or change the flag.
189  void toggleEndCondition();
190 
191  /// Test end interpolation
192  bool getEndInterpolation() const;
193 
194  // Insert or delete vertices. The insertion methods return the index if
195  // successful and -1 otherwise. The deletion methods return 0 if ok and
196  // -1 otherwise. The insertion methods create the point if it does not
197  // exist.
199  GA_Size where=0) override;
201  int deleteVertex(GA_Size num) override;
202 
203  // Assuming the curve is closed, "unroll" it so that the CVs that are
204  // shared to form a wrapped curve are made unique. Also, the curve becomes
205  // open. The base class method only flips the open flag. If the curve is
206  // not closed, the method returns -1. Otherwise it returns 0.
207  int unroll(int append_pts = 1) override;
208 
209  // Shift the array of vertices by an offset and wrap around.
210  // Cycle a subrange if the curve is closed and cycle the basis
211  // accordingly. The offset can be either negative or positive.
212  // Optionally remap the new basis to the original length and origin
213  int cycle(int amount, int keepSpan = 1) override;
214 
215  // Raise the number of CVs to match the newcount. The shape of the curve
216  // (especially if parametric) should NOT change. Return 0 upon success
217  // and -1 otherwise. start and stop define which indices to examine
218  // if newcount is negative it is taken as a relative value.
219  int loft(int newcount, int start=-1, int stop=-1) override;
220 
221  // If this curve is open and non-end-interpolating, insert knots such that
222  // it becomes end-interpolating without changing its shape. Return 0 if
223  // successful and -1 othewise.
224  int clamp(GA_PointGroup *delpoints = 0);
225  void unclamp();
226 
227  // Remove the interior knot at knotIdx num times if possible,
228  // where 1 <= num <= the multiplicity mult of the knot, and
229  // U[knotIdx] != U[knotIdx+1].
230  // If multiplicity mult is not given, the procedure will compute it.
231  // The tol specifies the tolerance of distance between the knot removable
232  // position and its actual position. To force knot removal, set tol= -1.0F
233  // The deleteGroup is used to gather unused cv geo points to be deleted.
234  // (It is more efficient to delete points in a group.)
235  // Note: During the process of knot removal, interior cvs geo points
236  // may changed and/or deleted.
237  // Output: the actual number of times that the knot got removed.
238 
239  int unrefine(int knotIdx, GA_AttributeRefMap &hlist,
240  int num, int mult = 0,
241  fpreal tol = 1e-4F,
242  GA_PointGroup *deleteGroup = 0);
243 
244  int unrefine(int knotIdx, int num, int mult = 0,
245  float tol = 1e-4F,
246  GA_PointGroup *deleteGroup = 0);
247 
248 
249  // Get error bound for removing of a knot once.
250  float getKnotRemovalBound(int knotIdx, int mult=0) const;
251 
252  // Merge a bunch of NURB curves together. The curves are assumed to
253  // be all NURBS, all of the same order and characteristics such as
254  // non/end-interp, open/closed.
255  static int mergeGroup(GEO_Detail *gdp, GA_PrimitiveGroup *nurbs);
256  static int mergeGroup(GEO_Detail *gdp, UT_Array<GEO_Primitive *> *nurbcurves_array);
257 
258  // Reverses the vertices of a given face.
259  void reverse() override;
260 
261  // If ustart and ustop are two values in the valid interval,ustart < ustop,
262  // return the part of curve defined by ustart and ustop in a new primitive.
263  // Return 0 if a problem is encountered.
264  GEO_Curve *extract(float ustart,float ustop) const override;
265 
266  const GA_PrimitiveJSON *getJSON() const override;
267 
268  /// Builds NURB curves using the specified range of point offsets,
269  /// as dictated by curvesizelist and curvepointnumbers, in parallel.
270  /// curvepointnumbers lists the *offsets* of the points used by
271  /// each curve *MINUS* startpt, i.e. they are offsets relative to startpt,
272  /// *not* indices relative to startpt. The offset of the first curve is
273  /// returned, and the rest are at consecutive offsets. All
274  /// curvepointnumbers must be between 0 (inclusive) and
275  /// npoints (exclusive).
276  ///
277  /// NOTE: Existing primitives *are* allowed to be using the points in
278  /// the specified range already, and the curves being created do not
279  /// need to use all of the points in the range. However,
280  /// these cases may impact performance.
281  /// @{
282  static GA_Offset buildBlock(GA_Detail *detail,
283  const GA_Offset startpt,
284  const GA_Size npoints,
285  const GEO_PolyCounts &curvesizelist,
286  const int *curvepointnumbers,
287  const UT_Array<int> &porders,
288  const int uorder = 4,
289  const bool closed = false,
290  const bool interpends = true);
291  static GA_Offset buildBlock(GA_Detail *detail,
292  const GA_Offset startpt,
293  const GA_Size npoints,
294  const GA_PolyCounts &curvesizelist,
295  const int *curvepointnumbers,
296  const UT_Array<int> &porders,
297  const int uorder = 4,
298  const bool closed = false,
299  const bool interpends = true);
300  /// @}
301 
302  fpreal calcPerimeter() const override;
303 
304 protected:
306  { return GEO_Curve::buildFamilyMask(); }
307 
308  /// All subclasses should call this method to register the curve intrinsics.
309  /// @see GA_IntrinsicManager
312  { return GEO_Curve::registerIntrinsics(defn); }
313 
314  // Get a new basis of a type that matches our type:
315  GA_Basis *newBasis() const override;
316 
317  /// Set the basis to a copy of the passed-in basis.
318  /// NOTE: basis *must* be valid for this curve!
319  void setBasisCopy(const GA_Basis *basis) override;
320 
321  // Parameter correction by Newton iteration.
322  void correctParam(const UT_Vector4 &p, float &u,
323  float distTol=1e-10F, float angTol=1e-2F,
324  int maxIter=50) const;
325 
326  // Protected methods which translate/transform selected breakpoints and
327  // perform an interpolation.
328  virtual int translateBkptsFixed(const UT_IntArray &uindices,
329  const UT_Vector3 &delta,
330  GA_PointGroup *ptgroup = NULL,
331  GEO_Delta *geodelta = 0);
332  virtual int transformBkptsFixed(const UT_IntArray &uindices,
333  const UT_Matrix4 &matx,
334  GA_PointGroup *ptgroup = NULL,
335  GEO_Delta *geodelta = 0);
336 
337  // Methods which translate/transform selected breakpoints and do not
338  // perform an interpolation.
339  int translateBkptsNonFixed(const UT_IntArray &uindices,
340  const UT_Vector3 &delta,
341  GA_PointGroup *ptgroup = NULL,
342  GEO_Delta *geodelta = 0);
343  int transformBkptsNonFixed(const UT_IntArray &uindices,
344  const UT_Matrix4 &matx,
345  GA_PointGroup *ptgroup = NULL,
346  GEO_Delta *geodelta = 0);
347 
348  // Increase the order. Return 0 if successful, -1 otherwise (eg.
349  // order cannot be increased because it's >= MAXORDER).
350  int raiseOrderRefMap(int neworder,
351  GA_AttributeRefMap &m) override;
352  int raiseOrderInt(int neworder) override;
353 
354  // Given a parameter in the face domain, insert as many CVs as necessary to
355  // create a discontinuity at the corresponding point on the curve.The shape
356  // of the curve should NOT change. Return u's index upon success and -1
357  // otherwise.
358  int subdivideRefMap(float u,
359  GA_AttributeRefMap &map) override;
360  int subdivideFloat(float u) override;
361 
362  // Change the multiplicity of the knot by inserting it "r" times after
363  // checking its current multiplicity. The maximum valid r for a knot is
364  // equal to the degree of the basis (ie order-1). Return -1 if k is outside
365  // the valid interval or greater than the number of CVs. Otherwise, return
366  // the index of the inserted knot and the initial multiplicity.
367  int refineRefMap(float k, GA_AttributeRefMap &hl,
368  int r=1) override;
369  int refineInt(float k,int r = 1) override;
370 private:
371  int xformBreakpoints(const UT_IntArray &uindices,
372  const UT_Vector3Array &trans,
373  GA_PointGroup *ptgroup = NULL,
374  GEO_Delta *geodelta = 0);
375 
376  // Merge the given basis into ours and refine the curve accordingly.
377  // It is assumed that both bases have the same order and that "basis"
378  // contains all our knots plus possibly others. Also, it is assumed that
379  // "basis" has been GA_Basis::map()-ed onto our knot interval. The
380  // method returns 0 if OK and -1 if problems.
381  // Finally, it is assumed that the basis has no knots of higher
382  // multiplicity than degree. This is not checked for here, so one
383  // must ensure the resulting basis is of proper length.
384  int merge(const GA_NUBBasis &basis);
385 
386  // Return the multiplicity of knot k, cycling the curve first and/or
387  // unsharing the wrapped points if necessary.
388  int alignKnot(float k, int &kidx,
389  int &cycfix, int &interpfix);
390  void unAlignKnot(int &kidx, int cycfix, int interpfix);
392 };
394 
395 #endif
virtual void open(int preserveShape=0, int safe=0)
static GA_IntrinsicManager::Registrar registerIntrinsics(GA_PrimitiveDefinition &defn)
Definition: GEO_TriMesh.h:192
virtual float getKnotLengths(GA_ParameterizationType ptype, UT_FloatArray &lengths) const =0
virtual int refineInt(float k, int r=1)
GA_API const UT_StringHolder div
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3460
GLenum clamp
Definition: glcorearb.h:1233
virtual int domainRangeOfCV(int cvidx, int &mink, int &maxk) const =0
void reverse() override
Reverse the order of vertices.
int attach(const GEO_Face &face, int blend=1, float bias=0.5f, float tolerance=1.0f, int unrefine=1, GA_PointGroup *ptgroup=0) override
virtual int breakpointRangeOfCV(int cvidx, int &minbkp, int &maxbkp) const =0
#define SYS_DEPRECATED_PUSH_DISABLE()
#define SYS_DEPRECATED_POP_DISABLE()
GLuint start
Definition: glcorearb.h:474
#define GA_MAXORDER
Definition: GA_Defines.h:17
3D Vector class.
virtual int loft(int newcount, int start=-1, int stop=-1)=0
virtual int warp(float u, const UT_Vector3 &delta, GA_AttributeRefMap &map, float sharpness=0.0f, float bias=-1.0f)=0
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:234
GA_PrimitiveFamilyMask
virtual int transformBreakpoints(const UT_IntArray &uindices, const UT_Matrix4 &matx, int fixbkpts=1, GA_PointGroup *ptgroup=NULL, GEO_Delta *geodelta=0)=0
#define GA_INVALID_OFFSET
Definition: GA_Types.h:677
GA_ParameterizationType
Definition: GA_Types.h:195
GA_Size GA_Offset
Definition: GA_Types.h:640
vint4 blend(const vint4 &a, const vint4 &b, const vbool4 &mask)
Definition: simd.h:4761
GLfloat bias
Definition: glew.h:10316
~GEO_PrimNURBCurve() override
virtual GA_Size appendVertex(GA_Offset ppt)
GA_API const UT_StringHolder trans
virtual int translateBreakpoints(const UT_IntArray &uindices, const UT_Vector3 &delta, int fixbkpts=1, GA_PointGroup *ptgroup=NULL, GEO_Delta *geodelta=0)=0
virtual GEO_Curve * extract(float ustart, float ustop) const =0
int refine(float k, GA_AttributeRefMap &gah, int r=1)
Definition: GEO_Face.h:301
virtual GD_Face * planar(GD_Detail &dgdp, int copyxy=0) const =0
virtual const GA_PrimitiveJSON * getJSON() const =0
GLuint num
Definition: glew.h:2695
Provide a JSON interface to a primitive.
fpreal calcPerimeter() const override
#define GEO_API
Definition: GEO_API.h:14
Bezier or NURBS basis classes which maintain knot vectors.
Definition: GA_Basis.h:49
virtual GA_Basis * newBasis() const =0
GEO_PrimNURBCurve(GA_Detail *d, GA_Offset offset=GA_INVALID_OFFSET)
NURBS basis classes which maintain knot vectors.
Definition: GA_NUBBasis.h:44
A handle to simplify manipulation of multiple attributes.
GLfloat GLfloat p
Definition: glew.h:16656
static GA_IntrinsicManager::Registrar registerIntrinsics(GA_PrimitiveDefinition &defn)
virtual int raiseOrderRefMap(int neworder, GA_AttributeRefMap &map)=0
virtual void close(int rounded=1, int preserveShape=0)
virtual int raiseOrderInt(int neworder)=0
GLuint GLdouble GLdouble GLint GLint uorder
Definition: glew.h:3462
virtual int cycle(int amount, int=1)
virtual int subdivideFloat(float u)
virtual int refineRefMap(float k, GA_AttributeRefMap &gah, int r=1)
fpreal64 fpreal
Definition: SYS_Types.h:277
virtual int subdivideRefMap(float u, GA_AttributeRefMap &map)
const GLdouble * m
Definition: glew.h:9166
GLfloat f
Definition: glcorearb.h:1925
Container class for all geometry.
Definition: GA_Detail.h:95
virtual GA_Size insertVertex(GA_Offset ppt, GA_Size where=0)
GLintptr offset
Definition: glcorearb.h:664
Definition of a geometric primitive.
virtual void reparameterize(GA_ParameterizationType ptype)=0
virtual int evaluateBasis(float u, float *ubvals, int &cvoffset, unsigned du=0, int uoffset=-1) const =0
virtual int evaluateBreakpoint(int uidx, UT_Vector4 &pos, int du=0) const =0
GLboolean r
Definition: glcorearb.h:1221
virtual int deleteVertex(GA_Size num)
static GA_PrimitiveFamilyMask buildFamilyMask()
Definition: GEO_Curve.h:419
GLenum GLuint GLint GLenum face
Definition: glew.h:4630
virtual int unroll(int append_pts=1)
virtual int evaluateBasisDerivs(float u, float bmatx[][GA_MAXORDER], int &cvoffset, unsigned du=0, int uoffset=-1) const =0
GLsizei GLenum GLenum GLuint GLenum GLsizei * lengths
Definition: glcorearb.h:2541
static GA_PrimitiveFamilyMask buildFamilyMask()
virtual void setBasisCopy(const GA_Basis *basis)=0
static GA_Offset buildBlock(GA_PrimitiveTypeId type, GA_Detail *detail, const GA_Offset startpt, const GA_Size npoints, const GEO_PolyCounts &facesizelist, const int *facepointnumbers, const bool closed=true)