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  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 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  virtual 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  virtual 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.
77  virtual float getKnotLengths(GA_ParameterizationType ptype,
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  virtual 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  virtual 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  virtual 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  virtual 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  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) override;
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) 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  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) override;
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 override;
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) override;
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) override;
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.
195  virtual GA_Size insertVertex(GA_Offset ppt=GA_INVALID_OFFSET, GA_Size where=0) override;
196  virtual GA_Size appendVertex(GA_Offset ppt=GA_INVALID_OFFSET) override;
197  virtual int deleteVertex(GA_Size num) override;
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) override;
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) override;
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) override;
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() override;
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 override;
261 
262  virtual const GA_PrimitiveJSON *getJSON() const override;
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  fpreal calcPerimeter() const override;
299 
300 protected:
302  { return GEO_Curve::buildFamilyMask(); }
303 
304  /// All subclasses should call this method to register the curve intrinsics.
305  /// @see GA_IntrinsicManager
308  { return GEO_Curve::registerIntrinsics(defn); }
309 
310  // Get a new basis of a type that matches our type:
311  virtual GA_Basis *newBasis(void) const override;
312 
313  /// Set the basis to a copy of the passed-in basis.
314  /// NOTE: basis *must* be valid for this curve!
315  virtual void setBasisCopy(const GA_Basis *basis) override;
316 
317  // Parameter correction by Newton iteration.
318  void correctParam(const UT_Vector4 &p, float &u,
319  float distTol=1e-10F, float angTol=1e-2F,
320  int maxIter=50) const;
321 
322  // Protected methods which translate/transform selected breakpoints and
323  // perform an interpolation.
324  virtual int translateBkptsFixed(const UT_IntArray &uindices,
325  const UT_Vector3 &delta,
326  GA_PointGroup *ptgroup = NULL,
327  GEO_Delta *geodelta = 0);
328  virtual int transformBkptsFixed(const UT_IntArray &uindices,
329  const UT_Matrix4 &matx,
330  GA_PointGroup *ptgroup = NULL,
331  GEO_Delta *geodelta = 0);
332 
333  // Methods which translate/transform selected breakpoints and do not
334  // perform an interpolation.
335  int translateBkptsNonFixed(const UT_IntArray &uindices,
336  const UT_Vector3 &delta,
337  GA_PointGroup *ptgroup = NULL,
338  GEO_Delta *geodelta = 0);
339  int transformBkptsNonFixed(const UT_IntArray &uindices,
340  const UT_Matrix4 &matx,
341  GA_PointGroup *ptgroup = NULL,
342  GEO_Delta *geodelta = 0);
343 
344  // Increase the order. Return 0 if successful, -1 otherwise (eg.
345  // order cannot be increased because it's >= MAXORDER).
346  virtual int raiseOrderRefMap(int neworder, GA_AttributeRefMap &m) override;
347  virtual int raiseOrderInt (int neworder) override;
348 
349  // Given a parameter in the face domain, insert as many CVs as necessary to
350  // create a discontinuity at the corresponding point on the curve.The shape
351  // of the curve should NOT change. Return u's index upon success and -1
352  // otherwise.
353  virtual int subdivideRefMap (float u, GA_AttributeRefMap &map) override;
354  virtual int subdivideFloat (float u) override;
355 
356  // Change the multiplicity of the knot by inserting it "r" times after
357  // checking its current multiplicity. The maximum valid r for a knot is
358  // equal to the degree of the basis (ie order-1). Return -1 if k is outside
359  // the valid interval or greater than the number of CVs. Otherwise, return
360  // the index of the inserted knot and the initial multiplicity.
361  virtual int refineRefMap(float k, GA_AttributeRefMap &hl, int r=1) override;
362  virtual int refineInt(float k,int r = 1) override;
363 private:
364  int xformBreakpoints(const UT_IntArray &uindices,
365  const UT_Vector3Array &trans,
366  GA_PointGroup *ptgroup = NULL,
367  GEO_Delta *geodelta = 0);
368 
369  // Merge the given basis into ours and refine the curve accordingly.
370  // It is assumed that both bases have the same order and that "basis"
371  // contains all our knots plus possibly others. Also, it is assumed that
372  // "basis" has been GA_Basis::map()-ed onto our knot interval. The
373  // method returns 0 if OK and -1 if problems.
374  // Finally, it is assumed that the basis has no knots of higher
375  // multiplicity than degree. This is not checked for here, so one
376  // must ensure the resulting basis is of proper length.
377  int merge(const GA_NUBBasis &basis);
378 
379  // Return the multiplicity of knot k, cycling the curve first and/or
380  // unsharing the wrapped points if necessary.
381  int alignKnot(float k, int &kidx,
382  int &cycfix, int &interpfix);
383  void unAlignKnot(int &kidx, int cycfix, int interpfix);
385 };
387 
388 #endif
virtual void open(int preserveShape=0, int safe=0)
static GA_IntrinsicManager::Registrar registerIntrinsics(GA_PrimitiveDefinition &defn)
Definition: GEO_TriMesh.h:258
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:302
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.
fpreal calcPerimeter() const override
#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:270
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:95
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:415
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)