HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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  virtual ~GEO_PrimNURBCurve() {}
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  virtual int evaluateBasisDerivs(float u, float bmatx[][GA_MAXORDER],
56  int &cvoffset, unsigned du = 0,
57  int uoffset = -1) const;
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  virtual int evaluateBasis(float u,float *ubvals, int &cvoffset,
65  unsigned du=0, int uoffset=-1) const;
66 
67  // Compute the location of the breakpoint. Return 0 if OK, else -1.
68  virtual int evaluateBreakpoint(int uidx, UT_Vector4 &pos,
69  int du=0) const;
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.
77  virtual float getKnotLengths(GA_ParameterizationType ptype,
78  UT_FloatArray &lengths) const;
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  virtual int domainRangeOfCV(int cvidx, int &mink,int &maxk) const;
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  virtual int breakpointRangeOfCV(int cvidx, int &minbkp,
92  int &maxbkp) const;
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  virtual void reparameterize(GA_ParameterizationType ptype);
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  virtual int warp(float u, const UT_Vector3 &delta,
106  GA_AttributeRefMap &map,
107  float sharpness = 0.0f, float bias = -1.0f);
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  virtual 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);
119  virtual 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);
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  virtual int attach(const GEO_Face &face, int blend = 1,
137  float bias = 0.5f, float tolerance = 1.0f,
138  int unrefine = 1,GA_PointGroup *ptgroup=0);
139 
140  // Build a planar (domain) face of the same type as us and with the same
141  // number of vertices. Copying the (x,y) values of our points to the planar
142  // face is optional.
143  virtual GD_Face *planar(GD_Detail &dgdp, int copyxy = 0) const;
144 
145  // Set the wrap or open flag, and make sure the basis knot vectors are
146  // consistent with the change. These functions are virtual by inheritance.
147 
148  // Convert a topologically open curve into a topologically closed one.
149  // The rounded flag is mainly for surface end caps to indicate a half cap
150  // or a full cap.
151  //
152  // If rounded = 1:
153  // closed rounded curve.
154  // non end interpolated.
155  // may or may not preserve shape depending on the flag.
156  // (however, always preserve shape if original curve is
157  // non end interpolated)
158  // If rounded = 0:
159  // closed curve with a straight edge.
160  // end interpolated.
161  // always preserve the shape. (ignore preserveShape flag)
162  virtual void close(int rounded = 1, int preserveShape = 0);
163 
164  // Convert a topologically closed curve into a topologically open one.
165  //
166  // For an end interpolation closed curve, we get (topologically) open
167  // curve:
168  // 1. For preserve shape:
169  // exactly the same shape without any open gap.
170  // end interpolated open curve.
171  // 2. For non preserve shape:
172  // hull remained but the curve changed shape with an open gap.
173  // end interpolated open curve.
174  //
175  // For a non end interpolation closed curve, we get (topologically) open
176  // curve:
177  // 1. For preserve shape:
178  // a portion of the original curve, thus have open gap.
179  // non end interpolated open curve.
180  // 2. For non preserve shape:
181  // hull remained but the curve changed shape with an open gap.
182  // Note: end interpolated open curve.
183  virtual void open(int preserveShape = 0, int = 0);
184 
185  // Check if the basis interpolates the endpoints, or change the flag.
186  void toggleEndCondition(void);
187 
188  /// Test end interpolation
189  bool getEndInterpolation() const;
190 
191  // Insert or delete vertices. The insertion methods return the index if
192  // successful and -1 otherwise. The deletion methods return 0 if ok and
193  // -1 otherwise. The insertion methods create the point if it does not
194  // exist.
197  virtual int deleteVertex(GA_Size num);
198 
199  // Assuming the curve is closed, "unroll" it so that the CVs that are
200  // shared to form a wrapped curve are made unique. Also, the curve becomes
201  // open. The base class method only flips the open flag. If the curve is
202  // not closed, the method returns -1. Otherwise it returns 0.
203  virtual int unroll(int append_pts = 1);
204 
205  // Shift the array of vertices by an offset and wrap around.
206  // Cycle a subrange if the curve is closed and cycle the basis
207  // accordingly. The offset can be either negative or positive.
208  // Optionally remap the new basis to the original length and origin
209  virtual int cycle(int amount, int keepSpan = 1);
210 
211  // Raise the number of CVs to match the newcount. The shape of the curve
212  // (especially if parametric) should NOT change. Return 0 upon success
213  // and -1 otherwise. start and stop define which indices to examine
214  // if newcount is negative it is taken as a relative value.
215  virtual int loft(int newcount, int start=-1, int stop=-1);
216 
217  // If this curve is open and non-end-interpolating, insert knots such that
218  // it becomes end-interpolating without changing its shape. Return 0 if
219  // successful and -1 othewise.
220  int clamp(GA_PointGroup *delpoints = 0);
221  void unclamp(void);
222 
223  // Remove the interior knot at knotIdx num times if possible,
224  // where 1 <= num <= the multiplicity mult of the knot, and
225  // U[knotIdx] != U[knotIdx+1].
226  // If multiplicity mult is not given, the procedure will compute it.
227  // The tol specifies the tolerance of distance between the knot removable
228  // position and its actual position. To force knot removal, set tol= -1.0F
229  // The deleteGroup is used to gather unused cv geo points to be deleted.
230  // (It is more efficient to delete points in a group.)
231  // Note: During the process of knot removal, interior cvs geo points
232  // may changed and/or deleted.
233  // Output: the actual number of times that the knot got removed.
234 
235  int unrefine(int knotIdx, GA_AttributeRefMap &hlist,
236  int num, int mult = 0,
237  fpreal tol = 1e-4F,
238  GA_PointGroup *deleteGroup = 0);
239 
240  int unrefine(int knotIdx, int num, int mult = 0,
241  float tol = 1e-4F,
242  GA_PointGroup *deleteGroup = 0);
243 
244 
245  // Get error bound for removing of a knot once.
246  float getKnotRemovalBound(int knotIdx, int mult=0) const;
247 
248  // Merge a bunch of NURB curves together. The curves are assumed to
249  // be all NURBS, all of the same order and characteristics such as
250  // non/end-interp, open/closed.
251  static int mergeGroup(GEO_Detail *gdp, GA_PrimitiveGroup *nurbs);
252  static int mergeGroup(GEO_Detail *gdp, UT_Array<GEO_Primitive *> *nurbcurves_array);
253 
254  // Reverses the vertices of a given face.
255  virtual void reverse();
256 
257  // If ustart and ustop are two values in the valid interval,ustart < ustop,
258  // return the part of curve defined by ustart and ustop in a new primitive.
259  // Return 0 if a problem is encountered.
260  virtual GEO_Curve *extract(float ustart,float ustop) const;
261 
262  virtual const GA_PrimitiveJSON *getJSON() const;
263 
264  /// Builds NURB curves using the specified range of point offsets,
265  /// as dictated by curvesizelist and curvepointnumbers, in parallel.
266  /// curvepointnumbers lists the *offsets* of the points used by
267  /// each curve *MINUS* startpt, i.e. they are offsets relative to startpt,
268  /// *not* indices relative to startpt. The offset of the first curve is
269  /// returned, and the rest are at consecutive offsets. All
270  /// curvepointnumbers must be between 0 (inclusive) and
271  /// npoints (exclusive).
272  ///
273  /// NOTE: Existing primitives *are* allowed to be using the points in
274  /// the specified range already, and the curves being created do not
275  /// need to use all of the points in the range. However,
276  /// these cases may impact performance.
277  /// @{
278  static GA_Offset buildBlock(GA_Detail *detail,
279  const GA_Offset startpt,
280  const GA_Size npoints,
281  const GEO_PolyCounts &curvesizelist,
282  const int *curvepointnumbers,
283  const UT_Array<int> &porders,
284  const int uorder = 4,
285  const bool closed = false,
286  const bool interpends = true);
287  static GA_Offset buildBlock(GA_Detail *detail,
288  const GA_Offset startpt,
289  const GA_Size npoints,
290  const GA_PolyCounts &curvesizelist,
291  const int *curvepointnumbers,
292  const UT_Array<int> &porders,
293  const int uorder = 4,
294  const bool closed = false,
295  const bool interpends = true);
296  /// @}
297 
298 protected:
300  { return GEO_Curve::buildFamilyMask(); }
301 
302  /// All subclasses should call this method to register the curve intrinsics.
303  /// @see GA_IntrinsicManager
306  { return GEO_Curve::registerIntrinsics(defn); }
307 
308  // Get a new basis of a type that matches our type:
309  virtual GA_Basis *newBasis(void) const;
310 
311  /// Set the basis to a copy of the passed-in basis.
312  /// NOTE: basis *must* be valid for this curve!
313  virtual void setBasisCopy(const GA_Basis *basis);
314 
315  // Parameter correction by Newton iteration.
316  void correctParam(const UT_Vector4 &p, float &u,
317  float distTol=1e-10F, float angTol=1e-2F,
318  int maxIter=50) const;
319 
320  // Protected methods which translate/transform selected breakpoints and
321  // perform an interpolation.
322  virtual int translateBkptsFixed(const UT_IntArray &uindices,
323  const UT_Vector3 &delta,
324  GA_PointGroup *ptgroup = NULL,
325  GEO_Delta *geodelta = 0);
326  virtual int transformBkptsFixed(const UT_IntArray &uindices,
327  const UT_Matrix4 &matx,
328  GA_PointGroup *ptgroup = NULL,
329  GEO_Delta *geodelta = 0);
330 
331  // Methods which translate/transform selected breakpoints and do not
332  // perform an interpolation.
333  int translateBkptsNonFixed(const UT_IntArray &uindices,
334  const UT_Vector3 &delta,
335  GA_PointGroup *ptgroup = NULL,
336  GEO_Delta *geodelta = 0);
337  int transformBkptsNonFixed(const UT_IntArray &uindices,
338  const UT_Matrix4 &matx,
339  GA_PointGroup *ptgroup = NULL,
340  GEO_Delta *geodelta = 0);
341 
342  // Increase the order. Return 0 if successful, -1 otherwise (eg.
343  // order cannot be increased because it's >= MAXORDER).
344  virtual int raiseOrderRefMap(int neworder, GA_AttributeRefMap &m);
345  virtual int raiseOrderInt (int neworder);
346 
347  // Given a parameter in the face domain, insert as many CVs as necessary to
348  // create a discontinuity at the corresponding point on the curve.The shape
349  // of the curve should NOT change. Return u's index upon success and -1
350  // otherwise.
351  virtual int subdivideRefMap (float u, GA_AttributeRefMap &map);
352  virtual int subdivideFloat (float u);
353 
354  // Change the multiplicity of the knot by inserting it "r" times after
355  // checking its current multiplicity. The maximum valid r for a knot is
356  // equal to the degree of the basis (ie order-1). Return -1 if k is outside
357  // the valid interval or greater than the number of CVs. Otherwise, return
358  // the index of the inserted knot and the initial multiplicity.
359  virtual int refineRefMap(float k, GA_AttributeRefMap &hl, int r=1);
360  virtual int refineInt(float k,int r = 1);
361 private:
362  int xformBreakpoints(const UT_IntArray &uindices,
363  const UT_Vector3Array &trans,
364  GA_PointGroup *ptgroup = NULL,
365  GEO_Delta *geodelta = 0);
366 
367  // Merge the given basis into ours and refine the curve accordingly.
368  // It is assumed that both bases have the same order and that "basis"
369  // contains all our knots plus possibly others. Also, it is assumed that
370  // "basis" has been GA_Basis::map()-ed onto our knot interval. The
371  // method returns 0 if OK and -1 if problems.
372  // Finally, it is assumed that the basis has no knots of higher
373  // multiplicity than degree. This is not checked for here, so one
374  // must ensure the resulting basis is of proper length.
375  int merge(const GA_NUBBasis &basis);
376 
377  // Return the multiplicity of knot k, cycling the curve first and/or
378  // unsharing the wrapped points if necessary.
379  int alignKnot(float k, int &kidx,
380  int &cycfix, int &interpfix);
381  void unAlignKnot(int &kidx, int cycfix, int interpfix);
383 };
385 
386 #endif
virtual void open(int preserveShape=0, int safe=0)
static GA_IntrinsicManager::Registrar registerIntrinsics(GA_PrimitiveDefinition &defn)
Definition: GEO_TriMesh.h:256
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
virtual int attach(const GEO_Face &face, int blend=1, float bias=0.5f, float tolerance=1.0f, int unrefine=1, GA_PointGroup *ptgroup=0)
virtual int domainRangeOfCV(int cvidx, int &mink, int &maxk) const =0
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:211
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:654
png_infop png_bytep * trans
Definition: png.h:2520
GA_ParameterizationType
Definition: GA_Types.h:173
virtual ~GEO_PrimNURBCurve()
GA_Size GA_Offset
Definition: GA_Types.h:617
GLfloat f
Definition: glcorearb.h:1925
virtual GA_Size appendVertex(GA_Offset ppt)
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:300
virtual GD_Face * planar(GD_Detail &dgdp, int copyxy=0) const =0
virtual const GA_PrimitiveJSON * getJSON() const =0
GLintptr offset
Definition: glcorearb.h:664
Provide a JSON interface to a primitive.
#define GEO_API
Definition: GEO_API.h:10
Bezier or NURBS basis classes which maintain knot vectors.
Definition: GA_Basis.h:49
virtual GA_Basis * newBasis(void) 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.
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 void reverse()
Reverse the order of vertices.
virtual int raiseOrderInt(int neworder)=0
double fpreal
Definition: SYS_Types.h:263
virtual int cycle(int amount, int=1)
virtual int subdivideFloat(float u)
virtual int refineRefMap(float k, GA_AttributeRefMap &gah, int r=1)
virtual int subdivideRefMap(float u, GA_AttributeRefMap &map)
Container class for all geometry.
Definition: GA_Detail.h:96
png_infop png_uint_32 int num
Definition: png.h:2158
virtual GA_Size insertVertex(GA_Offset ppt, GA_Size where=0)
Definition of a geometric primitive.
GLboolean r
Definition: glcorearb.h:1221
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
virtual int deleteVertex(GA_Size num)
static GA_PrimitiveFamilyMask buildFamilyMask()
Definition: GEO_Curve.h:413
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
GLenum clamp
Definition: glcorearb.h:1233
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)