HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GD_TrimLoop.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 handles trimming loops. Each loop is a series of
10  * bezier segments which in totality is closed. Loops themselves
11  * are embedded in a linked list of loops.
12  *
13  */
14 
15 #ifndef __GD_TrimLoop_h__
16 #define __GD_TrimLoop_h__
17 
18 #include "GD_API.h"
19 #include <UT/UT_Array.h>
20 #include <UT/UT_BoundingRect.h>
21 #include <UT/UT_IntArray.h>
22 #include <UT/UT_Vector2.h>
23 
24 class GD_TrimPiece;
25 class GD_TrimHitInfo;
26 class gdTrimIntersection;
27 class GD_Detail;
28 
30 {
31 public:
32  GD_TrimLoopFlags() { closed = 0; }
33  unsigned closed:1,
34  clockwise:1;
35 };
36 
38 {
41 };
42 
44 {
45  GD_UMIN = 0,
46  GD_VMIN = 1,
47  GD_UMAX = 2,
48  GD_VMAX = 3
49 };
50 
52 {
55 };
56 
57 
59 {
60 public:
61  // Constructor which creates an empty loop.
62  GD_TrimLoop();
63 
64  // Generates curve out of a list of pieces.
65  GD_TrimLoop(GD_TrimPiece *curve);
66 
67  // Destructor. Will destroy this loop and ALL children/later siblings.
68  ~GD_TrimLoop();
69 
70  int64 getMemoryUsage(bool inclusive) const;
71 
72  // Evaluates curves value at a specified parameter value. Returns 1 if
73  // successful and 0 otherwise.
74  int evaluate(float u, UT_Vector2 &pos) const;
75  int evaluate(float u, UT_Vector2 &pos, UT_Vector2 &der)
76  const;
77  int evaluateHead(UT_Vector2 &pos) const;
78  int evaluateTail(UT_Vector2 &pos) const;
79 
80  // Find approximate normal. normal is NOT normalized!
81  void evaluateNormal(UT_Vector3 &normal) const;
82 
83  // Find whether clockwise or counter clockwise:
84  void findDirection();
85 
86  // Is the loop closed? Result of cuts are not closed.
87  unsigned isClosed() const { return flags.closed; }
88 
89  // Close up the loop.
90  void close(int connect_ends = 0);
91 
92  // Find length:
93  float length() const;
94 
95  // Is the loop clockwise? Ie: is it trim out?
96  unsigned isClockwise() const { return flags.clockwise; }
97 
98  // Appends given loop to our loop list
99  void appendLoop(GD_TrimLoop *loop);
100 
101  // Appends the given loop to our loop piece list, then deletes the loop
102  // if the delete flag is set.
103  void append(GD_TrimLoop *loop, int consolidate = 0,
104  int deleteloop = 0,
105  int join = 0);
106 
107  // Appends a point to our loop through the simple expedient of
108  // generating a new GD_TrimPiece
109  void appendPoint(float u, float v);
110 
111  // Append at point of intersection. If no intersection, we return zero
112  // and don't append.
113  int appendAtIntersect(GD_TrimLoop *loop, int deleteloop,
114  float tol=1E-4F);
115 
116  // Append the given piece to our loop.
117  void append(GD_TrimPiece *piece);
118 
119  // Return a copy of myself & my siblings, or just myself. The second
120  // method erases the child and next information.
121  GD_TrimLoop *copy() const;
122  GD_TrimLoop *copyThis() const;
123 
124  // Reverse the loop orientation for myself & my siblings, or just myself.
125  void reverse();
126  void reverseThis();
127 
128  // 1 if given object is contained. Assumes no intersections
129  // Always zero if this is open.
130  // Only refers to this trim loop.
131  // Returns -1 if point/object is within tolerance.
132  // Jitter version tries up to three points above and below the given
133  // point until a consensus is reached. It is used by the primitive
134  // method.
135  int isInsideJitter(const UT_Vector2 &pt, float tol = 1e-4F,
136  float dither = 1e-5F) const;
137  int isInside(const GD_TrimLoop &prim, float tol = 1E-4F)
138  const;
139  int isInside(const UT_Vector2 &pt, float tol = 1E-4F)
140  const;
141 
142  // Returns one if point contained by this set of trim loops.
143  int isTrimmedIn(const UT_Vector2 &pt,
144  GD_TrimRule rule = GD_TrimWindingRule) const;
145  int isTrimmedIn(float u, float v,
146  GD_TrimRule rule = GD_TrimWindingRule) const;
147  // The valid loop list acts as a mask of which loops can be tested.
148  // They are ascending, and built from setLoopIds.
149  int isTrimmedIn(const UT_Vector2 &pt,
150  UT_IntArray &validloops,
151  GD_TrimRule rule = GD_TrimWindingRule) const;
152  int isTrimmedIn(float u, float v,
153  UT_IntArray &validloops,
154  GD_TrimRule rule = GD_TrimWindingRule) const;
155 
156  // Uses the slower, jittered method to ensure more accurate testing
157  int isTrimmedInJitter(const UT_Vector2 &pt,
158  GD_TrimRule rule = GD_TrimWindingRule) const;
159  int isTrimmedInJitter(float u, float v,
160  GD_TrimRule rule = GD_TrimWindingRule) const;
161  int isTrimmedIn(GD_TrimLoop *loop,
162  GD_TrimRule rule = GD_TrimWindingRule) const;
163 
164  void getParameterRange(float &umin, float &umax) const;
165 
166  // Returns distance in parameter space, closure aware.
167  float parametricDist(float u1, float u2) const;
168  // Returns length from u1 to u2 in increasing direction,
169  // closure aware.
170  float parametricLength(float u1, float u2) const;
171 
172  // Cuts out a piece of the trim loop. Resulting loop is open.
173  GD_TrimLoop *cut(float u1, float u2) const;
174 
175  // Cuts family of loops on isoparm, generating two copies, right & left.
176  // Acts in place, so copy before hand if req'd
177  void cutAtIsoparm(GD_TrimLoop **left, GD_TrimLoop **right,
178  GD_IsoparmDirection iso, float val,
179  float tol = 1e-4f);
180 
181  // Cuts family of loops into inside/outside components, as
182  // determined by the cutter group:
183  void cutAtTrim(GD_TrimLoop **inside, GD_TrimLoop **outside,
184  const GD_TrimLoop *cutter,
186 
187  // Intersects all the pieces, returning a list of hits.
188  int intersect(const GD_TrimLoop &loop,
189  UT_Array<GD_TrimHitInfo> &hitlist,
190  float tol = 1E-4F) const;
191 
192  // Intersects with all of this pieces, giving hit list
193  int intersect(GD_TrimPiece &piece,
194  UT_Array<GD_TrimHitInfo> &hitlist,
195  float tol = 1e-4F) const;
196 
197  // Intersects with all of loops hiearchy, giving hit list
198  int intersectAll(const GD_TrimLoop &loop,
199  UT_Array<GD_TrimHitInfo> &hitlist,
200  float tol = 1e-4F) const;
201 
202  // Intersects all pieces with the domain boundaries. The list is sorted
203  // in t:
204  int intersectDomain(const UT_BoundingRect &brect,
205  UT_Array<GD_TrimHitInfo> &hitlist,
206  float tol = 1E-4F) const;
207 
208  // Cuts at all boundary isoparms and returns a new loop (a new set of
209  // loops). Acts in place. Returns itself if the loop is closed or no
210  // intersection with the domain boundary is found.
211  GD_TrimLoop *domainClip(const UT_BoundingRect &brect,
212  float tol = 1E-4F, int preservedirection = 1);
213 
214  // Handles incremental tesselation of loop:
215  int startWalk(float inc, float minstep, float maxstep,
216  float &u, float &v);
217  // Returns 1 if more points.
218  int doWalk(float &u, float &v);
219  void endWalk();
220 
221  // Return all the loop data (including its siblings and kids) into the
222  // arrays provided. The return value has the number of loops. The arrays
223  // will not have the number of entries. This is for rib conversion mostly.
224  int getData(UT_IntArray &ncurves,
225  UT_IntArray &order, UT_IntArray &ncvs,
226  UT_FloatArray &knots,
229  UT_FloatArray &w) const;
230 
231  // set all the loop ids.
232  int setLoopIds(int id = 0);
233  int getId() const { return myId; }
234 
235  GD_TrimLoop *getNext() const { return myNext; }
236  GD_TrimLoop *getChild() const { return myChild; }
237 
238  GD_Detail *getDetail() const { return myDetail; }
239  void setDetail(GD_Detail *gdp) { myDetail = gdp; }
240 
241  // Altitude is the "sea level" were trimmed in/out boundaries
242  // occur.
243  GD_TrimLoop *preprocessLoops(GD_TrimRule rule, int altitude=0);
244 
245  // Finds maximum trimmed in height.
246  int getMaxHeight() const;
247 
248  // Finds maximum trimmed in height.
249  int getBaseDir() const;
250 
251  // Makes all trim loops be on the same level.
252  GD_TrimLoop *flatten();
253 
254  void print(int i = 1, int recurse = 1) const;
255 
256  // Returns whether the head is sufficiently close (within "tol") to the
257  // tail.
258  int isHeadNearTail(float tol=1E-4F) const;
259 
260  // Test whether the loop's head/tail is near the bound of the rectangle.
261  // Returns 1 if it's near the bound (and inserts/appends the hit info
262  // into the list.
263  int hitHead(const UT_BoundingRect &brect,
264  UT_Array<GD_TrimHitInfo> &hitlist,
265  float tol = 1E-4F) const;
266  int hitTail(const UT_BoundingRect &brect,
267  UT_Array<GD_TrimHitInfo> &hitlist,
268  float tol = 1E-4F) const;
269 
270  // Bridge two points, posa and posb, that lie on the domain boundary, with
271  // an open loop. "brect" is the bounding rectangle for the domain of the
272  // surface to be cut, while "bbox" is the bounding rectangle that contains
273  // both the curve and the domain. We would build the bridge outside bbox
274  // to avoid building a self intersecting curve. "tol" is the desired
275  // distance between bbox and the bridge.
276  // If always counter is true, we always build in counter clockwise
277  // direction
278  static GD_TrimLoop *domainBridge(const UT_BoundingRect &brect,
279  const UT_Vector2 &posa, float ua, GD_DomainBoundary a,
280  const UT_Vector2 &posb, float ub, GD_DomainBoundary b,
281  float tol, const UT_BoundingRect &bbox,
282  int alwayscounter = 0);
283 
284  // Get approximately "numdivs" number of points. if the flag "usebreak"
285  // is set, then, use the "evaluateBreakSeg" to get breakpoints along with
286  // other points. Otherwise, just get numdiv+1 points.
287  int getPoints(int numdivs, UT_Vector3Array &domain,
288  int usebreak);
289 
290  /// Walks over all trim pieces of this loop. Pass NULL to it in the first call,
291  /// and then the current piece in all subsequent calls. Once the traversal
292  /// reaches the end, a NULL pointer is returned.
293  GD_TrimPiece* getPiece(GD_TrimPiece* prev_piece) const;
294 
295 protected:
296  // For all loops in the network, ensure all internal pieces match
297  // up exactly.
298  void snapPieces();
299 
300  // This will transform the loop list into one which is winding
301  // compliant. Ie: No loops intersect (except at tangents), and
302  // the loop hiararchy has trim in loops at the top level followed
303  // by trim out loops as children thereof.
304  // NB: May delete this, returns new root.
305  GD_TrimLoop *applyWindingRule(int isfragmented = 0,
306  int altitude = 0,
307  int *maxdepth = 0,
308  int *basedir = 0);
309 
310  // Intersect two provided loops generating a new list of loops
311  // comprising the resulting pieces. Takes into account whether the
312  // sources are in the same direction.
313  // Returns NULL if no intersections.
314  GD_TrimLoop *fragment(const GD_TrimLoop *loop) const;
315 
316  // Intersects all pieces with the isoparm provided:
317  int intersect(float val, GD_IsoparmDirection isoparm,
318  UT_Array<GD_TrimHitInfo> &hitlist,
319  float tol = 1E-4F) const;
320 
321  // Return the number of hits after post processing the hit list generated
322  // by intersecting with an isoparm.
323  int processIsoparmHits(UT_Array<GD_TrimHitInfo> &hits,
324  int hit, float tol = 1E-4F) const;
325 
326  // Intersect with one isoparm and do internal stuff...
327  void doIsoparm(int isoparm, float val, float tol,
328  GD_DomainBoundary code,
329  UT_Array<GD_TrimHitInfo> &hitlist,
330  int &hit, int &i) const;
331 
332  // Adds loop as child if contained in this, otherwise as a sibling.
333  // NB: Loop's children are ignored and loops next pointer is destroyed.
334  // Thus, both must be NULL before calling.
335  // Returns new root, either this or loop.
336  GD_TrimLoop *addPossibleChild(GD_TrimLoop *loop);
337 
338  // Removes all degenerate loops. May delete this.
339  GD_TrimLoop *removeDegenerateLoops(float tol=1E-4F);
340 
341  // Removes all redundant loops in this loop tree. May delete this.
342  GD_TrimLoop *removeRedundantLoops();
343 
344  // Calculates depths of all loops
345  void findDepths(int depth);
346 
347  // Finds most trimmed in depth.
348  int findMaxDepth() const;
349 
350  // Finds trim direction of base loop:
351  int getBaseTrimDir() const;
352 
353  // Adjusts all depths by delta depth.
354  void adjustDepths(int deltadepth);
355 
356 public:
358 
359  // We own these:
361  GD_TrimPiece *myLastTrimPiece; // Tail pointer
362 private:
363  GD_TrimLoop *myNext, *myChild;
364  GD_Detail *myDetail;
366 
367  float myUStart, myULength;
368 
369  // Note we do NOT own this.
370  gdTrimIntersection *myNextIntersection;
371  // If we are a result of a cut, which curves contributed. Parent
372  // is source of cut, other parent is what was cut by. Latter must
373  // be set by the cutter.
374  // this != myParent->myChild!
375  GD_TrimLoop const *myParent;
376  GD_TrimLoop const *myOtherParent;
377  int inOtherParent; // Contained in other parent?
378  int myId; // Two loops with equal ids are
379  // considered to not intersect.
380  int myDepth; // How deep this loop is.
381 
382  // Current state information for walk:
383  GD_TrimPiece *myWalkPiece;
384  float myWalkU;
385  float myWalkUInc, myWalkMinStep2, myWalkMaxStep2;
386  float myWalkLastX, myWalkLastY;
387 
388  // State information for append to handle initial points:
389  UT_Vector2 myInitPoint;
390  int myHasInitPoint;
391 
392  // Return a copy of myself only.
393  GD_TrimLoop *doCopy() const;
394 };
395 
396 #endif
vint4 max(const vint4 &a, const vint4 &b)
Definition: simd.h:4703
int getId() const
Definition: GD_TrimLoop.h:233
GD_IsoparmDirection
Definition: GD_TrimLoop.h:37
GLuint GLdouble u1
Definition: glew.h:3446
GLint left
Definition: glew.h:8008
GLuint const GLfloat * val
Definition: glew.h:2794
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:9477
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2864
void reverse(I begin, I end)
Definition: pugixml.cpp:7190
GLsizei GLsizei GLchar * source
Definition: glew.h:1832
const GLdouble * v
Definition: glew.h:1391
ImageBuf OIIO_API flatten(const ImageBuf &src, ROI roi={}, int nthreads=0)
void close() override
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3446
GD_TrimRule
Definition: GD_TrimLoop.h:51
bool intersect(const Line3< T > &line, const Vec3< T > &v0, const Vec3< T > &v1, const Vec3< T > &v2, Vec3< T > &pt, Vec3< T > &barycentric, bool &front)
GLclampf f
Definition: glew.h:3499
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1890
GD_Detail * getDetail() const
Definition: GD_TrimLoop.h:238
GLuint GLsizei GLsizei * length
Definition: glew.h:1825
long long int64
Definition: SYS_Types.h:116
GLfloat right
Definition: glew.h:15186
GD_TrimLoop * getChild() const
Definition: GD_TrimLoop.h:236
GD_TrimPiece * myTrimPieces
Definition: GD_TrimLoop.h:360
void setDetail(GD_Detail *gdp)
Definition: GD_TrimLoop.h:239
unsigned isClosed() const
Definition: GD_TrimLoop.h:87
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
UT_BoundingRect myBBox
Definition: GD_TrimLoop.h:357
GD_TrimPiece * myLastTrimPiece
Definition: GD_TrimLoop.h:361
ImageBuf OIIO_API cut(const ImageBuf &src, ROI roi={}, int nthreads=0)
unsigned isClockwise() const
Definition: GD_TrimLoop.h:96
#define GD_API
Definition: GD_API.h:10
OIIO_API bool copy(string_view from, string_view to, std::string &err)
GD_TrimLoop * getNext() const
Definition: GD_TrimLoop.h:235
arg_join< It, char > join(It begin, It end, string_view sep)
Definition: format.h:3326
GLuint GLdouble GLdouble u2
Definition: glew.h:3446
vint4 min(const vint4 &a, const vint4 &b)
Definition: simd.h:4694
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glew.h:1254
GD_DomainBoundary
Definition: GD_TrimLoop.h:43
std::enable_if< internal::is_string< S >::value >::type print(std::basic_ostream< FMT_CHAR(S)> &os, const S &format_str, const Args &...args)
Definition: ostream.h:146