HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GEO_PolyInterface.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: GEO_PolyInterface.h ( GEO Library, C++)
7  *
8  * COMMENTS:
9  *
10  * GEO_PolyInterface provides a way of navigating and manipulating polygon
11  * mesh topologies. It is meant to replace GEO_HedgeInterface which provides
12  * the same function but attempts at maintain half-edge information
13  * transparently through intercepting topological operations performed on the
14  * detail in various ways. This approach proved to provide little advantage for
15  * the cost it pays in efficiency, not to mention the difficulty of maintenance
16  * every time a new topology manipulation method is added somewhere. In
17  * contrast GEO_PolyInterface is explicit and expects the user to use the
18  * provided methods for all topology manipulation between the point where the
19  * interface is constructed until it is destroyed (or hardenPolys() is called).
20  *
21  * Note that other operations on the detail such as creation, destruction,
22  * and manipulation of groups and attributes can be performed in the usual
23  * manner without interference with GEO_PolyInterface. Standard topology
24  * attributes can also be read as usual. So, operations such as vertexPoint(),
25  * vertexPrimitive(), pointVertex(), vertexToNextVertex() can still be called
26  * through the detail although GEO_PolyInterface provides aliases for these
27  * as well. Note also that the recently added methods for accessing primitive
28  * vertex lists or flags are also not compatible with GEO_PolyInterface and
29  * cannot be used while a GEO_PolyInterface is active on a detail.
30  *
31  * Furthermore, note that unlike GEO_HedgeInterface, GEO_PolyInterface
32  * abandons all aspirations of extending half-edges to primitive types other
33  * than polygons. In fact, even open polygons are not supported.
34  *
35  */
36 
37 #ifndef __GEO_PolyIface__
38 #define __GEO_PolyIface__
39 
40 #include "GEO_Detail.h"
41 #include "GEO_Hedge.h"
42 #include "GEO_PrimPoly.h"
43 
44 #include <GA/GA_ATITopology.h>
45 #include <GA/GA_AttributeRefMap.h>
46 #include <GA/GA_Range.h>
47 
48 #include <UT/UT_Triangulate.h>
49 
50 class GEO_PrimPoly;
51 
52 #define USE_32BIT_LINKS 1
53 #define VERIFY_WITH_HARD_POLYS 0
54 
55 #if USE_32BIT_LINKS
56 
57 #define FLAG_MASK 0x40000000
59 
60 #else // Use 64bit links
61 
62 #define FLAG_MASK 0x4000000000000000
63 typedef uint64 RawLinkType;
64 
65 #endif
66 
69 {
70  return (i & FLAG_MASK);
71 }
72 
75 {
76  return (i | FLAG_MASK);
77 }
78 
81 {
82  return (i & (~FLAG_MASK));
83 }
84 
85 /// Filtered Ranges are used to make range iterators over usual GA_Ranges
86 /// with additional filtering conditions.
87 
88 template <typename FILTER, typename ITERTYPE>
90 {
91  FilteredRange(const FILTER &f, const GA_Range &r) :
92  myFilter(f), myRange(r) { }
93 
94  struct Iterator
95  {
96  Iterator(const FILTER &f) : myFilter(f), myIter() { }
97  Iterator(const FILTER &f, const GA_Range &r) :
98  myFilter(f), myIter(r)
99  { nextValid(); }
100 
101  ITERTYPE operator*() const { return ITERTYPE(*myIter); }
102  bool operator!=(const Iterator &other)
103  { return !myIter.atEnd(); }
104  Iterator &operator++() { ++myIter; nextValid(); return *this; }
105 
106  void nextValid()
107  {
108  while (!myIter.atEnd() && !myFilter(*myIter))
109  ++myIter;
110  }
111 
112  private:
113  GA_Iterator myIter;
114  FILTER myFilter;
115  };
116 
117  Iterator begin() const { return Iterator(myFilter, myRange); }
118  Iterator end() const { return Iterator(myFilter); }
119 private:
120  FILTER myFilter;
121  GA_Range myRange;
122 };
123 
124 template <typename CIRCULATOR, typename ITERTYPE>
125 struct Cycle
126 {
127  Cycle(const CIRCULATOR &f, GA_Offset base) :
128  myCirculator(f), myBase(base) { }
129 
130  struct Iterator
131  {
132  Iterator(const CIRCULATOR &f, GA_Offset iter) :
133  myCirculator(f), myIter(iter), myBase(GA_INVALID_OFFSET) { }
134 
135  ITERTYPE operator*() const { return ITERTYPE(myIter); }
136  bool operator!=(const Iterator &other)
137  { return GAisValid(myIter) && myIter != myBase; }
139  {
140  if (!GAisValid(myBase))
141  myBase = myIter;
142  myIter = myCirculator(myIter);
143  return *this;
144  }
145 
146  private:
147  GA_Offset myIter, myBase;
148  CIRCULATOR myCirculator;
149  };
150 
151  Iterator begin() const
152  { return Iterator(myCirculator, myBase); }
153 
154  Iterator end() const
155  { return Iterator(myCirculator, myBase); }
156 private:
157  CIRCULATOR myCirculator;
158  GA_Offset myBase;
159 };
160 
162 {
163 public:
164 
166  const GA_PrimitiveGroup *polys = nullptr);
167 
169 
170  /// hardenPolys converts the soft polygons used by GEO_PolyInterface
171  /// into actual GEO_PrimPoly objects. You *MUST* harden your polygons
172  /// before trying to access a GEO_PrimPoly object. Of course you can
173  /// skip hardening the polygons, if you're working on a temporary
174  /// detail which is going to be tossed out. In that case you would
175  /// probably use copyPolys to write them into a different detail.
176  /// The copied polys will be the usual polygons and will need no
177  /// hardening.
178 
179  void hardenPolys();
180 
181  /// Copy current work set polygons into the given detail. The
182  /// pt_offset_map_attr point attribute can determine the point offset
183  /// in the target detail ino which each given point should be mapped.
184  /// A value of -1 indicates that the point must be created. The
185  /// attribute is non-const and is over-written at -1 entries with
186  /// the offset of the created point in the given detail. If grp
187  /// is given, only the polygons in (resp. out of) the given group are
188  /// copied, when copy_excluded is false (resp. true).
189 
190  GA_Offset copyPolys(GA_Detail *gdp,
191  GA_Attribute *pt_offset_map_attr = nullptr,
192  const GA_PrimitiveGroup *grp = nullptr,
193  bool copy_excluded = false);
194 
195  /// Add the given point/vertex/primitive attribute or those passing
196  /// the given filter to the list of attributes that are automatically
197  /// interpolated during operations.
198 
199  void wranglePointAttribute(GA_Attribute *attrib);
200  void wranglePointAttribute(
201  const GA_AttributeFilter &filter);
202 
203  void wrangleVertexAttribute(GA_Attribute *attrib);
204  void wrangleVertexAttribute(
205  const GA_AttributeFilter &filter);
206 
207  void wranglePrimitiveAttribute(GA_Attribute *attrib);
208  void wranglePrimitiveAttribute(
209  const GA_AttributeFilter &filter);
210 
211  /// Clear the list of wrangled point/vertex/primitive attributes.
212 
214  { deleteAttribRefMap(myPointAttrRefMap); }
215 
217  { deleteAttribRefMap(myVertexAttrRefMap); }
218 
220  { deleteAttribRefMap(myPrimitiveAttrRefMap); }
221 
222  /// Temporarily enable or disable all wrangling of point/vertex/primitive
223  /// attributes initiated by calling wranglePointAttributes(), etc.
224 
225  void enablePointWrangling(bool enable)
226  { myPointWranglingEnabled = enable;}
227 
228  void enableVertexWrangling(bool enable)
229  { myVertexWranglingEnabled = enable;}
230 
231  void enablePrimitiveWrangling(bool enable)
232  { myPrimitiveWranglingEnabled = enable;}
233 
234  /// Return the polygon to which the hedge belongs.
237  { return geo_hedge::hedgePrimitive(myGdp, h); }
238 
239  // Hedge to poly and poly to first hedge
241  { return vertexPrimitive(srcVertex(h)); }
242 
244  { return GEO_Hedge(polyFirst(poly)); }
245 
246  // Returns true if vtx is the source vertex of a valid half-edge.
249  { return GAisValid(vtx)
250  && GAisValid(symNext(vtx)); }
251 
252  /// Check whether a hedge is valid. A half-edge is valid if it is
253  /// belongs to a closed polygon in the group on which the interface
254  /// is constructed or is the result of the manipulation of such hedges.
257  { return isValidHedgeSrcVertex(srcVertex(h)); }
258 
260  bool isValid(GEO_Hedge h) const
261  { return isValidHedge(h); }
262 
263  /// returns true of h is the *primary* hedge in its equivalence class.
264  /// Each equivalence class of hedges at any time has a unique primary
265  /// hedge. This is used for example to enumerate over all edges in the
266  /// detail (as opposed to over all hedges).
268  bool isPrimary(GEO_Hedge h) const
269  { return !isSecondary(srcVertex(h)); }
270 
271  /// Returns the source vertex of the hedge.
274  { return geo_hedge::srcVertex(h); }
275 
276  /// Returns the destination vertex of the hedge.
279  { return geo_hedge::dstVertex(*this, h); }
280 
281  /// Returns the vertex preceding the source of the hedge in its polygon.
284  { return geo_hedge::preSrcVertex(*this, h); }
285 
286  /// Returns the vertex succeeding the destination of the hedge.
289  { return geo_hedge::postDstVertex(*this, h); }
290 
291  /// Returns the point to which the source vertex is wired.
294  { return geo_hedge::srcPoint(myGdp, h); }
295 
296  /// Returns the point to which the destination vertex is wired.
299  { return geo_hedge::dstPoint(*this, h); }
300 
301  /// Returns the point to which the preSrcVertex(h) is wired.
302  /// @see: preSrcVertex()
305  { return geo_hedge::preSrcPoint(*this, h); }
306 
307  /// Returns the point to which the postDstVertex(h) is wired.
308  /// @see: postDstVertex()
311  { return geo_hedge::postDstPoint(*this, h); }
312 
313  /// Returns the next hedge (hedge whose source is the destination of the
314  /// parameter hedge) in its polygon.
315 
318  { return geo_hedge::nextPrimitiveHedge(*this, h); }
319 
320  /// Quad-Edge/GQ alias for nextPrimitiveHedge().
323  { return nextPrimitiveHedge(h); }
324 
325  /// Returns the previous hedge (hedge whose destination is the source
326  /// of the parameter hedge) in its polygon.
329  { return geo_hedge::prevPrimitiveHedge(*this, h); }
330 
331  /// Quad-Edge/GQ alias for prevPrimitiveHedge().
334  { return prevPrimitiveHedge(h); }
335 
336  /// Returns the hedge other than the parameter hedge in its polygon that
337  // has pt as an endpoint.
340  GA_Offset pt) const;
341 
342  /// Returns the "next" equivalent hedge to h:
343  /// two hedges are equivalent if either their source and destination points
344  /// are the same or the source point of each is the destination point of
345  /// the other. Calling nextEquivalentHedge() repeatedly returns back to the
346  /// original hedge. Thus to check if hedge h is manifold hedge one can
347  // check that:
348  // nextEquivalentHedge(h) != h
349  // && nextEquivalentHedge(nextEquivalentHedge(h)) == h.
350  // Note that this only verifies that there are two distinct hedges in the
351  // class but does not verify that they are oriented oppositely.
354  { return GEO_Hedge(symNext(srcVertex(h))); }
355 
356  /// Quad-Edge/GQ alias for nextEquivalentHedge().
359  { return nextEquivalentHedge(h); }
360 
361  /// Returns the primary hedge equivalent to the argument hedge.
364  { return GEO_Hedge(findPrimary(srcVertex(h))); }
365 
366  /// Alias for primaryEquivalentHedge().
369  { return primaryEquivalentHedge(h); }
370 
371  /// Arbitrarily-Ordered Scan Methods:
372  /// These methods scan over all edge/hedges incident to a point in an
373  /// arbitrary order. NB. This order may be different in different
374  /// executions of the code or across different platforms.
375 
376  /// Returns a first incident hedge to a point. Together with
377  /// nextIncidentHedge, one can enumerate circularly over all hedges
378  /// incident to a point. A hedge is incident to a point if one of its
379  /// endpoints is that point.
382  { return geo_hedge::firstIncidentHedge(*this, p); }
383 
386  { return geo_hedge::nextIncidentHedge(*this, h, p); }
387 
388  /// Similar to first/nextIncidentHedge but stops only at the primary
389  /// hedge in each equivalence class of hedges involved.
392  { return geo_hedge::firstIncidentEdge(*this, p); }
393 
396  { return geo_hedge::nextIncidentEdge(*this, h, p); }
397 
398  /// Similar to first/nextIncidentHedge but using only outgoing hedges.
399  /// Note that nextOutgoingHedge does not need the parameter p anymore.
402  { return geo_hedge::firstOutgoingHedge(*this, p); }
403 
406  { return geo_hedge::nextOutgoingHedge(*this, h); }
407 
408  /// Similar to first/nextIncidentHedge but using only incoming hedges.
409  /// Note that nextOutgoingHedge does not need the parameter p anymore.
412  { return geo_hedge::firstIncomingHedge(*this, p); }
413 
416  { return geo_hedge::nextIncomingHedge(*this, h); }
417 
418  /// Manifold Scan Methods:
419 
420  /// A "manifold scan" around a point moves from one incoming (resp outgoing
421  /// hedge incident to a point to the next in counterclockwise order as
422  /// long as the hedge in question is a manifold hedge (i.h. it is
423  /// equivalent to exactly one other hedge oriented oppositely).
424 
425  /// Returns the first hedge with the same destination point as the argument
426  /// hedge that is reachable from it through a counterclockwise manifold
427  /// scan around the destination point.
428  /// Returns the argument hedge itself if either:
429  /// 1) it is already the first such hedge, or
430  /// 2) its source is an interior point of a manifold,
431  /// ie. a counterclockwise scan does a full circle.
434 
435 
436  /// Quad-Edge/GQ alias:
439  { return firstManifoldIncomingHedge(h); }
440  /// Returns the previous hedge with the same dst as h in a
441  /// counterclockwise manifold scan, returns GEO_INVALID_HEDGE if no
442  /// such hedge exists.
443  ///
444  /// NOTE: This is equivalent to dprev() operation in Quad-Edge
445  /// terminology, which is also used in GQ.
448 
449  /// Quad-Edge/GQ alias:
452  { return prevManifoldIncomingHedge(h); }
453 
454  /// Returns the next hedge with the same dst as h in a counterclockwise
455  /// manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
456  ///
457  /// NOTE: This is equivalent to dnext() operation in Quad-Edge
458  /// terminology, which is also used in GQ.
461 
462  /// Quad-Edge/GQ alias:
465  { return nextManifoldIncomingHedge(h); }
466 
467  /// Similar to firstManifoldIncomingHedge but finds the first hedge with
468  /// the same src as h in a counterclockwise scan from h.
471 
472  /// Quad-Edge/GQ alias:
475  { return firstManifoldOutgoingHedge(h); }
476 
477  /// Returns the previous hedge with the same src as h in a counterclockwise
478  // manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
479  ///
480  /// NOTE: This is equivalent to oprev() operation in Quad-Edge
481  /// terminology, which is also used in GQ or equivalently lnext(sym()).
484 
485  /// Alias for prevManifoldOutgoingHedge, equivalent to lnext(sym()).
488  { return prevManifoldOutgoingHedge(h); }
489 
490  /// Returns the next hedge with the same src as h in a counterclockwise
491  /// manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
492  ///
493  /// NOTE: This is equivalent to onext() operation in Quad-Edge
494  /// terminology, which is also used in GQ or equivalently sym(lprev()).
497 
498  /// Alias for nextManifoldOutgoingHedge, equivalent to sym(lprev()).
501  { return nextManifoldOutgoingHedge(h); }
502 
503  /// Returns true if the hedge h is a manifold hedge, if accept_bd is
504  /// false, this means that the equivalence class of h consists of
505  /// exactly two hedges oriented oppositely. If accept_bd is true, then
506  /// the equivalence class of h can also consist of a single (boundary)
507  /// half-edge.
510  bool accept_bd = false) const;
511 
512  /// Returns true if the hedge h is a boundary hedge, i.e. if its
513  /// equivalence class is singleton.
516  { return geo_hedge::isBoundaryHedge(*this, h); }
517 
518  /// Returns true if the hedge h is a bridge hedge, i.e. if is a
519  /// manifold hedge and its other equivalent hedge belongs to the
520  /// same primitive as h does.
523  { return geo_hedge::isBridgeHedge(*this, h); }
524 
525  /// Returns true if h1 and h2 are equivalent hedges with opposite
526  /// orientation.
528  bool areOpposite(GEO_Hedge h1, GEO_Hedge h2) const
529  { return geo_hedge::areOpposite(*this, h1, h2); }
530 
531  /// Returns true if h1 and h2 are equivalent hedges.
533  bool areEquivalent(GEO_Hedge h1, GEO_Hedge h2) const
534  { return geo_hedge::areEquivalent(*this, h1, h2); }
535 
536  /// Returns the number of hedges in the equivalence class of h.
539  { return geo_hedge::numEquivalentHedges(*this, h); }
540 
541  /// Returns the number if *edges* incident to a point (equivalent hedges
542  /// count as 1).
545  { return geo_hedge::numIncidentEdges(*this, pt); }
546 
547  /// Returns the number of distinct *hedges* incident to pt
550  { return geo_hedge::numIncidentHedges(*this, pt); }
551 
552  /// Find a hedge with the given endpoints or return GEO_INVLAID_HEDGE
555  GA_Offset p1) const;
556 
557  /// Rotate h forward, provided that h is a manifold hedge (equivalent
558  /// to exactly one other hedge f oppositely oriented. This is not checked
559  /// and the topology may be corrupted if rotate is applied to non-manifold
560  /// or boundary edges. Returns the resulting hedge which happens to be
561  /// equal to h (The input hedge will be the hedge that rotates (same src
562  /// vertex) and the same holds for the equivalent edge of h.
563  ///
564  /// ------>------> ------>------>
565  /// ^ |^ | ^ /7|
566  /// | || | | // |
567  /// | h || | ===> | h // |
568  /// | || | | // |
569  /// | v| v | // v
570  /// <------<------ |L/<---<------
571  ///
572  /// Note that this operation is precisely an edge flip if the two
573  /// primitives involved are triangles.
574  GEO_Hedge rotateForward(GEO_Hedge h);
575 
576  /// Complete reverse of rotateForward (all the point, vertex, and
577  /// primitive offsets are restored). When the incident primitives are
578  /// triangles, rotating forward or backward result in the same edge but
579  /// they are not exactly identical. In particular, two consecutive flips
580  /// on the same edge will reverse the orientation of the edge.
581  GEO_Hedge rotateBackward(GEO_Hedge h);
582 
583  /// Returns true if h can be flipped without the result overlapping an
584  /// existing hedge. In other words, h is flippable if its endpoints are
585  /// not endpoints of an existing edge in the geometry before the flip that
586  /// is not equivalent to h.
587  bool isFlippable(GEO_Hedge h) const;
588 
589  /// Flip h (provided that h is shared between two triangles) and is
590  /// flippable. Returns the resulting (flipped) hedge (equal to h) or
591  /// GEO_INVALID_HEDGE if h is not flippable.
592  GEO_Hedge flip(GEO_Hedge h);
593 
594  /// unflip is the reverse of a flip. Doing a flip followed by an unflip
595  /// should result in the same mesh with the same vertex/point/primtive
596  /// offsets and indices (but the vertices within primitives may shift).
597  GEO_Hedge unflip(GEO_Hedge h);
598 
599  /// Returns true if the hedge h is contractible, i.e. contracting h does
600  /// not force a a non-trivial (separating) cycle to collapse. A separating
601  /// cycle is a closed sequence of edges that if removed (together with
602  /// their incident geometry elements) the number of connected components
603  // increases. Contracting a non-contractible edge will split geometry into
604  /// multiple components.
605  bool isContractible(GEO_Hedge h) const;
606 
607  /// Contracts h.
608  /// @parameter on_dst, if true, causes the src point to move to the
609  /// position of the dst point. Otherwise, the dst point
610  /// is moved to the src point's position.
611  /// @parameter ratio, if in [0.0 .. 1.0], places the point of contraction
612  /// in a convex combination with biases ratio and
613  /// 1.0 - ratio from src and dst (or the other way around
614  /// if on_dst is false) respectively.
615 
616  // The internal flag distinguishes two different policies on whether
617  // the neighbouring triangles to the ones being destroyed as the result of
618  // the contraction of the edge inherit any of the half-edges of the latter
619  // triangles. If internal is set to true, the half-edge preceding or
620  // following each collapsing half-edge (depending on whether on_dst is true
621  // or not and whether the half-edge is oriented similarly to h or not) is
622  // inherited by the neighbouring triangle at the other half-edge sharing
623  // a vertex with the one being collapsed. If internal is false though,
624  // all half-edges of the destroyed triangles are destroyed and the others
625  // survive and are unified in the expected manner.
626 
627  GA_Offset contract(GEO_Hedge h, bool on_dst = true,
628  fpreal ratio = -1.0,
629  bool check_contractible = true,
630  bool internal = true);
631 
632  /// Splits the hedge h and its incident polygon (assumed to be a triangle,
633  /// although it doesn't fail if it isn't).
634  /// @parameter ratio determines the position of the new point at which the
635  /// hedge is split.
636  /// @parameter and_equivalent if true also splits all other hedges
637  /// equivalent to h at the same point.
638  /// @parameter pt is an optional point offset assumed to be located in
639  // the correct position (as given by ratio). This allows
640  // the caller to reuse points already created.
641  GEO_Hedge split(GEO_Hedge h, fpreal ratio,
642  bool and_equivalent = true,
644 
645  /// Inserts a point in the middle of a hedge and divides into two hedges.
646  ///
647  /// @parameter ratio determines the position of the new point at which the
648  /// hedge is split.
649  /// @parameter and_equivalent if true also divides all other hedges
650  /// equivalent to h at the same point.
651  /// @parameter pt is an optional point offset assumed to be located in
652  // the correct position (as given by ratio). This allows
653  // the caller to reuse points already created.
655  bool and_equivalent = true,
657 
658  /// Break a polygon into two polygons by dividing it along a diagonal.
659  /// The hedges starting from h_keep and ending before h_drop are kept in
660  /// the current polygon while the hedges starting at h_drop and ending
661  /// before h_keep end up in the new polygon. The returned hedge will be
662  /// one added to the original polygon corresponding to the cut diagonal.
663  /// NB. h_keep and h_drop *must* belong to the same polygon and cannot
664  /// be the same or consecutive hedges.
665  GEO_Hedge divide(GA_Offset poly, GEO_Hedge h_keep,
666  GEO_Hedge h_drop);
667 
668  /// Split a polygon at its barycenter, or a given point. If the point
669  /// is not given, then the position of the created point is set to the
670  /// barycenter of the polygon.
671  GA_Offset split(GA_Offset poly,
673 
674  /// Triangualtes a polygon.
675 
676  template <typename T = fpreal32>
677  exint triangulate(GA_Offset poly,
678  UT_Vector3T<T> *sym_ctr = nullptr,
679  GA_ROHandleT< UT_Vector3T<T> > pos_handle
681  GEO_Hedge start_hedge = GEO_INVALID_HEDGE,
682  UT_Array< UT_Vector3T<T> > *pos3 = nullptr,
683  UT_Array< UT_Vector2T<T> > *pos2 = nullptr,
684  UT_Triangulate::WorkBuffer *wb = nullptr,
685  UT_IntArray *tris = nullptr);
686 
687  template <typename S, typename T = fpreal32>
688  exint triangulate(const S &&polys,
689  UT_Vector3T<T> *sym_ctr = nullptr,
690  GA_ROHandleT< UT_Vector3T<T> > pos_handle
692 
693  // Deletes the *star* of a point. The star of a point in a polygonal
694  // complex consists of all edges and polygons incident to that point.
695  // So, deleting the star of an internal point on a manifold should leave
696  // a hole behind. If the cap_link is true, the hole is capped
697  // (if possible) with a new polygon. For this be possible the point *must*
698  // be an internal manifold point. If capping is possible then one of
699  // the polygons previously incident to pt can be specified as cap_poly
700  // to extend and become the patching polygon. If this polygon is not
701  // specified or is not actually incident to pt, then a new polygon will
702  // be created. The point pt itself is destroyed if destroy_pt is true.
703 
704  void deletePointStar(GA_Offset pt, bool cap_hole = true,
705  GA_Offset cap_poly = GA_INVALID_OFFSET,
706  bool destroy_pt = true);
707 
708 
709  // Dissolve the edge represented by h. The edge to be dissolved must be
710  // an interior manifold edge with consistent winding in the two polygons
711  // sharing it. Return value is true if h is dissovled and false if
712  // the dissolving has failed.
713  bool dissolve(GEO_Hedge h);
714 
715  void wireVertexPoint(GA_Offset vtx, GA_Offset pt,
716  bool rewire_hedges = true);
717 
718  /// Basic polygon manipulation methods. You should use these instead of
719  /// those offered by GEO_PrimPoly while dealing with softened polys.
720 
721  GA_Offset appendPoly();
722 
724  bool isValidPoly(GA_Offset poly) const
725  { return GAisValid(poly)
726  && GAisValid(polyFirst(poly)); }
727 
728  void destroyPoly(GA_Offset poly, bool and_pts = false);
729 
730  GA_Offset appendVertex(GA_Offset poly, GA_Offset pt,
731  bool relink_hedges = true);
732 
733  GA_Offset insertVertex(GA_Offset poly, GA_Offset pt,
734  GA_Offset before = GA_INVALID_OFFSET,
735  bool relink_hedges = true);
736 
737  GA_Offset stealVertex(GA_Offset poly, GA_Offset vtx,
738  GA_Offset insert_before = GA_INVALID_OFFSET,
739  bool relink_hedges = true);
740 
741  int deleteVertex(GA_Offset vtx, bool relink_hedges = true);
742 
743  int vertexCount(GA_Offset poly) const;
744 
745  GA_Detail *getDetail() const { return myGdp; }
746 
747  bool softValidate() const;
748  bool validate() const;
749 
751  GA_Offset prevPrimVertex(GA_Offset v) const;
752 
754  GA_Offset nextPrimVertex(GA_Offset v) const;
755 
757  void getAdjacentPrimVertices(GA_Offset v, GA_Offset &vprev,
758  GA_Offset &vnext) const;
759 
760  void dumpHedge(GA_Offset vtx);
762  { dumpHedge(srcVertex(h)); }
763 
764  // For a given polygon offset controlled by this interface, polyFirst()
765  // returns the first vertex in the circular list of vertices of that
766  // polygon. If a polygon is not modified by the interface this will be
767  // the first vertex of the input polygon. Also, when the polygon is
768  // hardened, this will be its first vertex.
769 
771  GA_Offset polyFirst(GA_Offset poly) const;
772 
773  // Given a vertex of a polygon, returns the next vertex in its
774  // circular list of vertices.
777  { return GA_Offset(myNextPolyHedge->getLink(v)); }
778 
779  // Given a vertex of a polygon, returns the previous vertex in its
780  // circular list of vertices.
783  { return GA_Offset(myPrevPolyHedge->getLink(v)); }
784 
785  UT_Vector3 calcBarycenter(GA_Offset poly) const;
786 
787  struct PolyFilter
788  {
789  explicit PolyFilter(const GEO_PolyInterface &pi) : myPI(pi) { }
790  bool operator()(GA_Offset off) const
791  { return myPI.isValidPoly(off); }
792 
793  private:
794  const GEO_PolyInterface &myPI;
795  };
797 
798  struct HedgeFilter
799  {
800  explicit HedgeFilter(const GEO_PolyInterface &pi) :
801  myPI(pi) { }
802 
803  bool operator()(GA_Offset off) const
804  { return myPI.isValidHedge(GEO_Hedge(off)); }
805 
806  private:
807  const GEO_PolyInterface &myPI;
808  };
810 
812  {
813  explicit PrimaryHedgeFilter(const GEO_PolyInterface &pi) :
814  myPI(pi) { }
815 
816  bool operator()(GA_Offset off) const
817  { return myPI.isValidHedge(GEO_Hedge(off))
818  && myPI.isPrimary(GEO_Hedge(off)); }
819  private:
820  const GEO_PolyInterface &myPI;
821  };
823 
824  PolyRange polys(const GA_PrimitiveGroup *g = nullptr,
825  bool complement = false) const;
826  HedgeRange hedges(const GA_VertexGroup *g = nullptr) const;
827  PrimaryHedgeRange primaryHedges(const GA_VertexGroup *g = nullptr) const;
828 
830  {
831  explicit PolyCirculator(const GEO_PolyInterface &pi) :
832  myPI(pi) { }
833 
835  { return myPI.polyNext(off); }
836  private:
837  const GEO_PolyInterface &myPI;
838  };
839 
841 
842  /// Returns the hedges around a polygon as a PolyCycle.
844  { return PolyCycle(PolyCirculator(*this),
845  polyFirst(poly)); }
846 
847 private:
848 
849  /// Get or set previous or next hedge in the circular list of hedges
850  /// equivalent (sym) to the one with source v.
851  ///
852  /// The equivalence class of a hedge consists of all hedges whose two
853  /// endpoints coincide with those of the hedge in question (although they
854  /// may be reversely paired). By *endpoints* of a hedge we mean the two
855  /// points into which the tail and head vertex of a hedge are respectively
856  /// wired.
857  /// @note Starting with any valid hedge, repeated calls to prevSymHedge
858  /// or enxtSym traverses all hedges to the original one and
859  /// ultimately wraps around.
860 
862  void symPrev(GA_Offset v, GA_Offset w);
863 
865  GA_Offset symPrev(GA_Offset v) const
866  { return myPrevSymHedge->getLink(v); }
867 
869  void symNext(GA_Offset v, GA_Offset w);
870 
872  GA_Offset symNext(GA_Offset v) const;
873 
874 
875  /// Form a singleton half-edge equivalence class over src_vtx. Clearly,
876  /// the formed half-edge will be primary.
877  /// NB. This should be the ONLY way of creating a valid half-edge outside
878  /// of the buildHedgeTopology().
879 
881  void symLoop(GA_Offset src_vtx);
882 
883 
885  bool isPrimary(GA_Offset v) const
886  { return !isSecondary(v); }
888  bool isSecondary(GA_Offset v) const;
889 
891  void makePrimary(GA_Offset v);
892 
894  void makeSecondary(GA_Offset v);
895 
896  /// returns the primary hedge in the equivalence class of a given hedge
897  GA_Offset findPrimary(GA_Offset vtx) const;
898 
899  /// Methods for finding hedges along the boundary of a given polygon.
901  void polyFirst(GA_Offset poly, GA_Offset v);
902 
903 
905  void polyPrev(GA_Offset v, GA_Offset w)
906  { myPrevPolyHedge->setLink(v, w); }
907 
909  void polyNext(GA_Offset v, GA_Offset w)
910  { myNextPolyHedge->setLink(v, w); }
911 
913  void polyLoop(GA_Offset src_vtx);
914 
916  void getAdjacentBoundaryVertices(GA_Offset vtx,
917  GA_Offset &prev_vtx,
918  GA_Offset &next_vtx) const;
919 
921  bool isHard(GA_Offset v) const
922  { return !isSoft(v); }
924  bool isSoft(GA_Offset poly) const;
925 
927  void makeHard(GA_Offset poly);
928 
930  void makeSoft(GA_Offset poly);
931 
933  GA_Offset vertexPoint(GA_Offset vtx) const
934  { return myGdp->vertexPoint(vtx); }
935 
937  void vertexPoint(GA_Offset vtx, GA_Offset pt)
938  { myTopology.wireVertexPoint(vtx, pt); }
939 
941  GA_Offset vertexToNextVertex(GA_Offset vtx) const
942  { return myGdp->vertexToNextVertex(vtx); }
943 
945  GA_Offset pointVertex(GA_Offset vtx) const
946  { return myGdp->pointVertex(vtx); }
947 
949  GA_Offset vertexPrimitive(GA_Offset vtx) const
950  { return myGdp->vertexPrimitive(vtx); }
951 
953  void vertexPrimitive(GA_Offset vtx, GA_Offset p)
954  { myTopology.wireVertexPrimitive(vtx, p); }
955 
956  void symUnlink(GA_Offset tailv);
957 
958  void symLink(GA_Offset src_vtx,
959  GA_Offset into_vtx = GA_INVALID_OFFSET);
960 
961  GA_Offset symFind(GA_Offset src_vtx, GA_Offset dst_vtx);
962 
963  /// This should remain the only possible way of assigning GA_INVALID_OFFSET
964  /// to a specific hedge sym next, effectively rendering it invalid. That's
965  /// aside from the default attrbute value being the same.
966 
968  void invalidateHedge(GA_Offset src_vtx)
969  {
970  myNextSymHedge->setLink(src_vtx,
972 
973  void symRelink(GA_Offset src_vtx,
974  GA_Offset into_src_vtx = GA_INVALID_OFFSET);
975 
976  void symRelinkJoint(GA_Offset vtx, GA_Offset prev_into,
977  GA_Offset vtx_into);
978 
979  void symRelinkJoint(GA_Offset vtx);
980  void wireVertexPointAndRelinkHedges(GA_Offset vtx,
981  GA_Offset pt, GA_Offset prev_into_src_vtx,
982  GA_Offset next_into_src_vtx);
983 
984  // Deprecated, kept for a couple of unported methods.
986  GEO_PrimPoly *hedgePrimPoly(GEO_Hedge h) const;
987 
988  const GEO_PrimPoly *getPrimPoly(GA_Offset primoff) const;
989  GEO_PrimPoly *getPrimPoly(GA_Offset primoff);
990 
991  typedef std::pair<GA_Offset, GA_Offset> OffsetPair;
992  typedef UT_Array<OffsetPair> OffsetPairArray;
993 
994  void buildHedgeTopology(const GA_PrimitiveGroup *polys);
995 
996  void linkPointIncidentHedges(GA_Offset pt,
997  OffsetPairArray &pairs_local,
998  const GA_PrimitiveGroup *polys,
999  UT_IntArray &index_cache);
1000 
1001  void polyLink(GA_Offset vtx, GA_Offset prev,
1002  GA_Offset next);
1003 
1004  void polyUnlink(GA_Offset vtx,
1005  bool release_from_poly = true);
1006 
1007  bool verifyPoly(GA_Offset poly) const;
1008 
1010  void copyVtxAttribs(GA_Offset dst, GA_Offset src);
1011 
1013  void lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1014  GA_Offset src1, fpreal bias);
1016  void copyPtAttribs(GA_Offset dst, GA_Offset src);
1017 
1019  void lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1020  GA_Offset src1, fpreal bias);
1022  void copyPrimAttribs(GA_Offset dst, GA_Offset src);
1023 
1025  void lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1026  GA_Offset src1, fpreal bias);
1027 
1028  GEO_Hedge splitHedgeSrc(GEO_Hedge h, GA_Offset pt,
1029  bool local_split_edge_link,
1030  GA_Offset link0 = GA_INVALID_OFFSET,
1031  GA_Offset link1 = GA_INVALID_OFFSET,
1032  fpreal lerp_ratio = 0.5);
1033 
1034  GEO_Hedge splitHedgeDst(GEO_Hedge h, GA_Offset pt,
1035  bool local_split_edge_link,
1036  GA_Offset link0 = GA_INVALID_OFFSET,
1037  GA_Offset link1 = GA_INVALID_OFFSET,
1038  fpreal lerp_ratio = 0.5);
1039 
1040 
1041  void deleteAttribRefMap(GA_AttributeRefMap *&r)
1042  { delete r; r = nullptr; }
1043 
1044  bool contractHedgeSrc(GEO_Hedge h);
1045  bool contractHedgeDst(GEO_Hedge h);
1046 
1047 
1049  bool compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1050  UT_IntArray &index_cache);
1051 
1052  GA_Detail *myGdp;
1053 
1054  GA_ATITopology *myPrevSymHedge;
1055  GA_ATITopology *myNextSymHedge;
1056  GA_ATITopology *myPrevPolyHedge;
1057  GA_ATITopology *myNextPolyHedge;
1058  GA_ATITopology *myFirstPolyHedge;
1059 
1060  GA_Topology &myTopology;
1061 
1062  GA_AttributeRefMap *myPointAttrRefMap;
1063  GA_AttributeRefMap *myVertexAttrRefMap;
1064  GA_AttributeRefMap *myPrimitiveAttrRefMap;
1065 
1066  GA_OffsetArray myTempOffsetArray1;
1067  GA_OffsetArray myTempOffsetArray2;
1068 
1069  bool myPointWranglingEnabled;
1070  bool myVertexWranglingEnabled;
1071  bool myPrimitiveWranglingEnabled;
1072 };
1073 
1074 void
1075 GEO_PolyInterface::symPrev(GA_Offset v, GA_Offset w)
1076 {
1077  if (!GAisValid(w))
1078  myPrevSymHedge->setLink(v, GA_INVALID_OFFSET);
1079  else
1080  myPrevSymHedge->setLink(v, w);
1081 }
1082 
1083 void
1084 GEO_PolyInterface::symNext(GA_Offset v, GA_Offset w)
1085 {
1088 
1089  bool secondary = isSecondary(v);
1090  auto raw = RawLinkType(w);
1091  if (secondary)
1092  raw = setLinkFlag(raw);
1093  myNextSymHedge->setLink(v, GA_Offset(raw));
1094 }
1095 
1096 GA_Offset
1097 GEO_PolyInterface::symNext(GA_Offset v) const
1098 {
1099  GA_Offset off = myNextSymHedge->getLink(v);
1100  if (!GAisValid(off))
1101  return GA_INVALID_OFFSET;
1102 
1103  // Clear the secondary bit if set!
1104  return GA_Offset(clearLinkFlag(RawLinkType(off)));
1105 }
1106 
1107 void
1109 {
1110  if (!GAisValid(v))
1111  myFirstPolyHedge->setLink(poly, GA_INVALID_OFFSET);
1112  else
1113  {
1114  // Preserve the soft bit!
1115  bool soft = isSoft(poly);
1116  auto raw = RawLinkType(v);
1117  if (soft)
1118  raw = setLinkFlag(raw);
1119  myFirstPolyHedge->setLink(poly, GA_Offset(raw));
1120  }
1121 }
1122 
1123 GA_Offset
1125 {
1126  GA_Offset v = myFirstPolyHedge->getLink(poly);
1127  if (!GAisValid(v))
1128  return v;
1129 
1130  // Clear the soft bit if set!
1131  return GA_Offset(clearLinkFlag(RawLinkType(v)));
1132 }
1133 
1134 bool
1135 GEO_PolyInterface::isSecondary(GA_Offset v) const
1136 {
1137  return getLinkFlag(RawLinkType(myNextSymHedge->getLink(v)));
1138 }
1139 
1140 void
1141 GEO_PolyInterface::makeSecondary(GA_Offset v)
1142 {
1143  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1144  myNextSymHedge->setLink(v, GA_Offset(setLinkFlag(raw)));
1145 }
1146 
1147 void
1148 GEO_PolyInterface::makePrimary(GA_Offset v)
1149 {
1150  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1151  myNextSymHedge->setLink(v, GA_Offset(clearLinkFlag(raw)));
1152 }
1153 
1154 bool
1155 GEO_PolyInterface::isSoft(GA_Offset poly) const
1156 {
1157  return getLinkFlag(RawLinkType(myFirstPolyHedge->getLink(poly)));
1158 }
1159 
1160 void
1161 GEO_PolyInterface::makeSoft(GA_Offset poly)
1162 {
1163  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1164  myFirstPolyHedge->setLink(poly, GA_Offset(setLinkFlag(raw)));
1165 }
1166 
1167 void
1168 GEO_PolyInterface::makeHard(GA_Offset poly)
1169 {
1170  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1171  myFirstPolyHedge->setLink(poly, GA_Offset(clearLinkFlag(raw)));
1172 }
1173 
1174 void
1175 GEO_PolyInterface::symLoop(GA_Offset src_vtx)
1176 {
1177  myNextSymHedge->setLink(src_vtx, src_vtx);
1178  myPrevSymHedge->setLink(src_vtx, src_vtx);
1179 
1180  // NB. Semantically, symLoop() must make src_vtx primary. Since our
1181  // implementation of making primary works by removing the secondary
1182  // bit which in this case has never been set anyway, we skip this.
1183  //
1184  // makePrimary(src_vtx);
1185 }
1186 
1187 void
1188 GEO_PolyInterface::polyLoop(GA_Offset src_vtx)
1189 {
1190  polyPrev(src_vtx, src_vtx);
1191  polyNext(src_vtx, src_vtx);
1192 }
1193 
1194 GA_Offset
1196 {
1197  return polyPrev(v);
1198 }
1199 
1200 GA_Offset
1202 {
1203  return polyNext(v);
1204 }
1205 
1206 void
1208  GA_Offset &vnext) const
1209 {
1210  // TODO: we probably should get rid of this one.
1211  vprev = polyPrev(v);
1212  vnext = polyNext(v);
1213 }
1214 
1215 GEO_Hedge
1217 {
1218  return geo_hedge::firstManifoldIncomingHedge(*this, h);
1219 }
1220 
1221 GEO_Hedge
1223 {
1224  return geo_hedge::prevManifoldIncomingHedge(*this, h);
1225 }
1226 
1227 GEO_Hedge
1229 {
1230  return geo_hedge::nextManifoldIncomingHedge(*this, h);
1231 }
1232 
1233 GEO_Hedge
1235 {
1236  return geo_hedge::firstManifoldOutgoingHedge(*this, h);
1237 }
1238 
1239 GEO_Hedge
1241 {
1242  return geo_hedge::nextManifoldOutgoingHedge(*this, h);
1243 }
1244 
1245 GEO_Hedge
1247 {
1248  return geo_hedge::prevManifoldOutgoingHedge(*this, h);
1249 }
1250 
1251 GEO_Hedge
1253 {
1254  return geo_hedge::findHedgeWithEndpoints(*this, p0, p1);
1255 }
1256 
1257 bool
1259 {
1260  return geo_hedge::isManifoldHedge(*this, h, accept_bd);
1261 }
1262 
1263 GEO_Hedge
1265 {
1266  return geo_hedge::otherPrimitiveHedgeAtPoint(*this, h, pt);
1267 }
1268 
1269 GEO_PrimPoly *
1270 GEO_PolyInterface::hedgePrimPoly(GEO_Hedge h) const
1271 {
1272  GA_Offset primoff = myGdp->vertexPrimitive(srcVertex(h));
1273  return static_cast<GEO_PrimPoly *>(myGdp->getPrimitive(primoff));
1274 }
1275 
1276 void
1277 GEO_PolyInterface::copyVtxAttribs(GA_Offset dst, GA_Offset src)
1278 {
1279  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1280  myVertexAttrRefMap->copyValue(GA_ATTRIB_VERTEX, dst,
1281  GA_ATTRIB_VERTEX, src);
1282 }
1283 
1284 void
1285 GEO_PolyInterface::lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1286  GA_Offset src1, fpreal b)
1287 {
1288  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1289  myVertexAttrRefMap->lerpValue(GA_ATTRIB_VERTEX, dst,
1290  GA_ATTRIB_VERTEX, src0, src1, b);
1291 }
1292 
1293 void
1294 GEO_PolyInterface::copyPtAttribs(GA_Offset dst, GA_Offset src)
1295 {
1296  if (myPointAttrRefMap && myPointWranglingEnabled)
1297  myPointAttrRefMap->copyValue(GA_ATTRIB_POINT, dst,
1298  GA_ATTRIB_POINT, src);
1299 }
1300 
1301 void
1302 GEO_PolyInterface::lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1303  GA_Offset src1, fpreal b)
1304 {
1305  if (myPointAttrRefMap && myPointWranglingEnabled)
1306  myPointAttrRefMap->lerpValue(GA_ATTRIB_POINT, dst,
1307  GA_ATTRIB_POINT, src0, src1, b);
1308 }
1309 
1310 void
1311 GEO_PolyInterface::copyPrimAttribs(GA_Offset dst, GA_Offset src)
1312 {
1313  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1314  myPrimitiveAttrRefMap->copyValue(GA_ATTRIB_PRIMITIVE, dst,
1315  GA_ATTRIB_PRIMITIVE, src);
1316 }
1317 
1318 void
1319 GEO_PolyInterface::lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1320  GA_Offset src1, fpreal b)
1321 {
1322  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1323  myPrimitiveAttrRefMap->lerpValue(GA_ATTRIB_PRIMITIVE, dst,
1324  GA_ATTRIB_PRIMITIVE, src0, src1, b);
1325 }
1326 
1327 bool
1328 GEO_PolyInterface::compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1329  UT_IntArray &index_cache)
1330 {
1331  if (v0 == v1)
1332  return false;
1333 
1334  if (index_cache(v0) < 0 || index_cache(v1) < 0)
1335  {
1336  GA_Offset poly = vertexPrimitive(v0);
1337  GA_Offset v_first = polyFirst(poly);
1338  if (!GAisValid(v_first))
1339  return false;
1340 
1341  int i = 0;
1342  GA_Offset v = v_first;
1343  do
1344  {
1345  index_cache(v) = i++;
1346  v = polyNext(v);
1347  } while (v != v_first);
1348  }
1349 
1350  UT_ASSERT_P(index_cache(v0) >= 0 && index_cache(v1) >= 0);
1351  return index_cache(v0) < index_cache(v1);
1352 }
1353 
1354 
1355 #endif
SYS_FORCE_INLINE GEO_Hedge lnext(GEO_Hedge h) const
Quad-Edge/GQ alias for nextPrimitiveHedge().
GEO_Hedge firstOutgoingHedge(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:504
SYS_FORCE_INLINE GEO_Hedge nextPrimitiveHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:255
SYS_FORCE_INLINE GA_Offset dstVertex(GEO_Hedge h) const
Returns the destination vertex of the hedge.
SYS_FORCE_INLINE GA_Offset preSrcPoint(GEO_Hedge h) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:189
SYS_FORCE_INLINE GEO_Hedge firstManifoldIncomingHedge(GEO_Hedge h) const
Manifold Scan Methods:
SYS_FORCE_INLINE GEO_Hedge prevPrimitiveHedge(GEO_Hedge h) const
GEO_Hedge firstManifoldIncomingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:687
SYS_FORCE_INLINE bool areOpposite(T &iface, GEO_Hedge e1, GEO_Hedge e2)
Definition: GEO_Hedge.h:364
SYS_FORCE_INLINE GEO_Hedge onext(GEO_Hedge h) const
Alias for nextManifoldOutgoingHedge, equivalent to sym(lprev()).
SYS_FORCE_INLINE bool isManifoldHedge(T &iface, GEO_Hedge e, bool accept_bd)
Definition: GEO_Hedge.h:332
SYS_FORCE_INLINE GA_Primitive * getPrimitive(GA_Offset prim_off)
Definition: GA_Detail.h:369
SYS_FORCE_INLINE GEO_Hedge dfirst(GEO_Hedge h) const
Quad-Edge/GQ alias:
FilteredRange< PrimaryHedgeFilter, GEO_Hedge > PrimaryHedgeRange
PolyFilter(const GEO_PolyInterface &pi)
SYS_FORCE_INLINE GEO_Hedge primaryEquivalentHedge(GEO_Hedge h) const
Returns the primary hedge equivalent to the argument hedge.
SYS_FORCE_INLINE GEO_Hedge prevManifoldOutgoingHedge(GEO_Hedge h) const
Returns the previous hedge with the same src as h in a counterclockwise.
SYS_FORCE_INLINE GA_Offset preSrcPoint(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:239
void resetPointWrangling()
Clear the list of wrangled point/vertex/primitive attributes.
Iteration over a range of elements.
Definition: GA_Iterator.h:28
SYS_FORCE_INLINE GEO_Hedge nextEquivalentHedge(GEO_Hedge h) const
GEO_Hedge firstManifoldOutgoingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:672
SYS_FORCE_INLINE GA_Offset getLink(GA_Offset ai) const
SYS_FORCE_INLINE bool isPrimary(GEO_Hedge h) const
Cycle< PolyCirculator, GEO_Hedge > PolyCycle
SYS_FORCE_INLINE bool isValidHedgeSrcVertex(GA_Offset vtx) const
const GLdouble * v
Definition: glcorearb.h:836
SYS_FORCE_INLINE GEO_Hedge dprev(GEO_Hedge h) const
Quad-Edge/GQ alias:
SYS_FORCE_INLINE GEO_Hedge dnext(GEO_Hedge h) const
Quad-Edge/GQ alias:
Iterator begin() const
bool GAisValid(GA_Size v)
Definition: GA_Types.h:625
GA_Size numIncidentHedges(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:839
bool operator()(GA_Offset off) const
void dumpHedge(GEO_Hedge h)
SYS_FORCE_INLINE GA_Offset srcVertex(GEO_Hedge h) const
Returns the source vertex of the hedge.
GLboolean GLboolean g
Definition: glcorearb.h:1221
SYS_FORCE_INLINE GA_Offset polyNext(GA_Offset v) const
GEO_Hedge nextIncomingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:572
SYS_FORCE_INLINE bool isBoundaryHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:298
GA_Offset srcVertex(GEO_Hedge)
Definition: GEO_Hedge.h:166
GA_Offset operator()(GA_Offset off) const
void lerpValue(GA_AttributeOwner downer, GA_Offset dest, GA_AttributeOwner owner, GA_Offset s0, GA_Offset s1, fpreal t) const
SYS_FORCE_INLINE GA_Offset srcPoint(const GA_Detail *gdp, GEO_Hedge e)
Definition: GEO_Hedge.h:173
SYS_FORCE_INLINE GA_Offset dstPoint(GEO_Hedge h) const
Returns the point to which the destination vertex is wired.
SYS_FORCE_INLINE GEO_Hedge firstIncidentEdge(GA_Offset p) const
GEO_Hedge nextManifoldOutgoingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:610
#define GEO_INVALID_HEDGE
An invalid hedge is sometimes returned if an operation is unsuccessful.
Definition: GEO_Hedge.h:32
GEO_Hedge nextIncidentEdge(T &iface, GEO_Hedge e, GA_Offset point)
Definition: GEO_Hedge.h:487
Iterator(const FILTER &f)
3D Vector class.
2D Vector class.
Definition: UT_Vector2.h:137
bool operator()(GA_Offset off) const
png_uint_32 i
Definition: png.h:2877
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:211
FilteredRange< PolyFilter, GA_Offset > PolyRange
void enablePointWrangling(bool enable)
GEO_Hedge nextManifoldIncomingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:657
uint32 RawLinkType
#define GA_INVALID_OFFSET
Definition: GA_Types.h:654
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:101
SYS_FORCE_INLINE GEO_Hedge nextOutgoingHedge(GEO_Hedge h) const
A range of elements in an index-map.
Definition: GA_Range.h:42
PolyCirculator(const GEO_PolyInterface &pi)
SYS_FORCE_INLINE GA_Offset dstVertex(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:202
SYS_FORCE_INLINE GA_Offset prevPrimVertex(GA_Offset v) const
SYS_FORCE_INLINE GA_Offset nextPrimVertex(GA_Offset v) const
SYS_FORCE_INLINE GEO_Hedge nextIncomingHedge(GEO_Hedge h) const
GA_Size GA_Offset
Definition: GA_Types.h:617
SYS_FORCE_INLINE GA_Primitive * hedgePrimitive(GEO_Hedge h) const
Return the polygon to which the hedge belongs.
bool atEnd() const
Definition: GA_Iterator.h:100
SYS_FORCE_INLINE GEO_Hedge oprev(GEO_Hedge h) const
Alias for prevManifoldOutgoingHedge, equivalent to lnext(sym()).
GEO_Hedge firstIncomingHedge(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:553
GEO_Hedge firstIncidentEdge(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:467
SYS_FORCE_INLINE GA_Offset postDstVertex(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:218
GLfloat f
Definition: glcorearb.h:1925
SYS_FORCE_INLINE bool isBoundaryHedge(GEO_Hedge h) const
unsigned long long uint64
Definition: SYS_Types.h:101
SYS_FORCE_INLINE GEO_Hedge findHedgeWithEndpoints(GA_Offset p0, GA_Offset p1) const
Find a hedge with the given endpoints or return GEO_INVLAID_HEDGE.
SYS_FORCE_INLINE GA_Offset postDstPoint(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:247
SYS_FORCE_INLINE GEO_Hedge ofirst(GEO_Hedge h) const
Quad-Edge/GQ alias:
SYS_FORCE_INLINE bool areEquivalent(GEO_Hedge h1, GEO_Hedge h2) const
Returns true if h1 and h2 are equivalent hedges.
int64 exint
Definition: SYS_Types.h:109
GEO_Hedge encapsulates a half-edge (hedge) which is the restriction of.
Definition: GEO_Hedge.h:47
SYS_FORCE_INLINE GEO_Hedge lprev(GEO_Hedge h) const
Quad-Edge/GQ alias for prevPrimitiveHedge().
SYS_FORCE_INLINE bool isValidPoly(GA_Offset poly) const
SYS_FORCE_INLINE bool isValid(GEO_Hedge h) const
SYS_FORCE_INLINE GEO_Hedge primary(GEO_Hedge h) const
Alias for primaryEquivalentHedge().
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE RawLinkType clearLinkFlag(RawLinkType i)
SYS_FORCE_INLINE bool isManifoldHedge(GEO_Hedge h, bool accept_bd=false) const
SYS_FORCE_INLINE GA_Offset srcPoint(GEO_Hedge h) const
Returns the point to which the source vertex is wired.
#define GEO_API
Definition: GEO_API.h:10
SYS_FORCE_INLINE GA_Offset preSrcVertex(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:210
SYS_FORCE_INLINE bool areOpposite(GEO_Hedge h1, GEO_Hedge h2) const
A handle to simplify manipulation of multiple attributes.
SYS_FORCE_INLINE void getAdjacentPrimVertices(GA_Offset v, GA_Offset &vprev, GA_Offset &vnext) const
SYS_FORCE_INLINE GEO_Hedge firstManifoldOutgoingHedge(GEO_Hedge h) const
GA_Detail * getDetail() const
GEO_Hedge prevManifoldOutgoingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:626
SYS_FORCE_INLINE GA_Offset postDstVertex(GEO_Hedge h) const
Returns the vertex succeeding the destination of the hedge.
SYS_FORCE_INLINE bool getLinkFlag(RawLinkType i)
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
GEO_Hedge prevManifoldIncomingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:643
bool operator!=(const Iterator &other)
void enablePrimitiveWrangling(bool enable)
bool operator()(GA_Offset off) const
Iterator end() const
SYS_FORCE_INLINE GA_Size numEquivalentHedges(GEO_Hedge h) const
Returns the number of hedges in the equivalence class of h.
SYS_FORCE_INLINE GA_Offset dstPoint(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:231
SYS_FORCE_INLINE const GA_Primitive * hedgePrimitive(const GA_Detail *gdp, GEO_Hedge e)
Definition: GEO_Hedge.h:187
SYS_FORCE_INLINE RawLinkType setLinkFlag(RawLinkType i)
SYS_FORCE_INLINE GEO_Hedge firstOutgoingHedge(GA_Offset p) const
GLfloat v0
Definition: glcorearb.h:815
SYS_FORCE_INLINE bool isValidHedge(GEO_Hedge h) const
ITERTYPE operator*() const
SYS_FORCE_INLINE GA_Offset preSrcVertex(GEO_Hedge h) const
Returns the vertex preceding the source of the hedge in its polygon.
Cycle(const CIRCULATOR &f, GA_Offset base)
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2001
SYS_FORCE_INLINE GA_Offset vertexPrimitive(GA_Offset vertex) const
Definition: GA_Detail.h:477
GLenum GLenum dst
Definition: glcorearb.h:1792
double fpreal
Definition: SYS_Types.h:263
bool operator!=(const Iterator &other)
GEO_Hedge nextOutgoingHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:519
SYS_FORCE_INLINE GEO_Hedge firstIncomingHedge(GA_Offset p) const
GEO_Hedge findHedgeWithEndpoints(T &iface, GA_Offset p0, GA_Offset p1)
Definition: GEO_Hedge.h:800
SYS_FORCE_INLINE GEO_Hedge otherPrimitiveHedgeAtPoint(GEO_Hedge h, GA_Offset pt) const
Returns the hedge other than the parameter hedge in its polygon that.
Iterator(const CIRCULATOR &f, GA_Offset iter)
SYS_FORCE_INLINE bool areEquivalent(T &iface, GEO_Hedge e1, GEO_Hedge e2)
Definition: GEO_Hedge.h:287
Iterator(const FILTER &f, const GA_Range &r)
SYS_FORCE_INLINE GA_Size numIncidentHedges(GA_Offset pt) const
Returns the number of distinct hedges incident to pt.
SYS_FORCE_INLINE GEO_Hedge prevManifoldIncomingHedge(GEO_Hedge h) const
GLfloat GLfloat v1
Definition: glcorearb.h:816
FilteredRange< HedgeFilter, GEO_Hedge > HedgeRange
HedgeFilter(const GEO_PolyInterface &pi)
SYS_FORCE_INLINE GA_Offset polyFirst(GA_Offset poly) const
PolyCycle polyHedges(GA_Offset poly) const
Returns the hedges around a polygon as a PolyCycle.
SYS_FORCE_INLINE GEO_Hedge otherPrimitiveHedgeAtPoint(T &iface, GEO_Hedge e, GA_Offset point)
Definition: GEO_Hedge.h:271
GA_Offset hedgePoly(GEO_Hedge h) const
Iterator & operator++()
SYS_FORCE_INLINE GEO_Hedge nextIncidentEdge(GEO_Hedge h, GA_Offset p) const
GEO_Hedge nextIncidentHedge(T &iface, GEO_Hedge e, GA_Offset pt)
Definition: GEO_Hedge.h:406
Container class for all geometry.
Definition: GA_Detail.h:96
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
Iterator end() const
GEO_Hedge firstIncidentHedge(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:383
hboost::disable_if< hboost::is_integral< T >, T >::type divide(const T &a, const T &b)
Definition: Composite.h:155
SYS_FORCE_INLINE GEO_Hedge nextManifoldIncomingHedge(GEO_Hedge h) const
SYS_FORCE_INLINE GEO_Hedge prevPrimitiveHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:263
SYS_FORCE_INLINE bool isBridgeHedge(GEO_Hedge h) const
SYS_FORCE_INLINE GEO_Hedge nextIncidentHedge(GEO_Hedge h, GA_Offset p) const
GLboolean r
Definition: glcorearb.h:1221
SYS_FORCE_INLINE GEO_Hedge nextManifoldOutgoingHedge(GEO_Hedge h) const
GEO_Hedge polyHedge(GA_Offset poly) const
#define FLAG_MASK
GA_Size numIncidentEdges(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:820
SYS_FORCE_INLINE GA_Size numEquivalentHedges(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:348
SYS_FORCE_INLINE GEO_Hedge sym(GEO_Hedge h) const
Quad-Edge/GQ alias for nextEquivalentHedge().
SYS_FORCE_INLINE GEO_Hedge firstIncidentHedge(GA_Offset p) const
void copyValue(GA_AttributeOwner downer, GA_Offset doffset, GA_AttributeOwner sowner, GA_Offset soffset) const
Automatically expand attribute data pages for threading.
bool isBridgeHedge(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:305
ITERTYPE operator*() const
void enableVertexWrangling(bool enable)
PrimaryHedgeFilter(const GEO_PolyInterface &pi)
FilteredRange(const FILTER &f, const GA_Range &r)
SYS_FORCE_INLINE GA_Offset polyPrev(GA_Offset v) const
SYS_FORCE_INLINE GA_Size numIncidentEdges(GA_Offset pt) const
Iterator begin() const
SYS_FORCE_INLINE GA_Offset postDstPoint(GEO_Hedge h) const
SYS_FORCE_INLINE GEO_Hedge nextPrimitiveHedge(GEO_Hedge h) const
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1296
GLenum src
Definition: glcorearb.h:1792
unsigned int uint32
Definition: SYS_Types.h:29
SYS_FORCE_INLINE void setLink(GA_Offset ai, GA_Offset v)