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