HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 
168  /// Having made an exact duplicate of a detail that has a PolyInterface,
169  /// (typically created using a call to replaceWith()), this constructor
170  /// makes a duplicated of the original interface. Without building the
171  /// topology from scratch.
172 
174  const GEO_PolyInterface *pip);
175 
177 
178 
179 
180  /// hardenPolys converts the soft polygons used by GEO_PolyInterface
181  /// into actual GEO_PrimPoly objects. You *MUST* harden your polygons
182  /// before trying to access a GEO_PrimPoly object. Of course you can
183  /// skip hardening the polygons, if you're working on a temporary
184  /// detail which is going to be tossed out. In that case you would
185  /// probably use copyPolys to write them into a different detail.
186  /// The copied polys will be the usual polygons and will need no
187  /// hardening.
188 
189  void hardenPolys();
190 
191  /// Copy current work set polygons into the given detail. The
192  /// pt_offset_map_attr point attribute can determine the point offset
193  /// in the target detail ino which each given point should be mapped.
194  /// A value of -1 indicates that the point must be created. The
195  /// attribute is non-const and is over-written at -1 entries with
196  /// the offset of the created point in the given detail. If grp
197  /// is given, only the polygons in (resp. out of) the given group are
198  /// copied, when copy_excluded is false (resp. true).
199 
200  GA_Offset copyPolys(GA_Detail *gdp,
201  GA_Attribute *pt_offset_map_attr = nullptr,
202  const GA_PrimitiveGroup *grp = nullptr,
203  bool copy_excluded = false);
204 
205  /// Add the given point/vertex/primitive attribute or those passing
206  /// the given filter to the list of attributes that are automatically
207  /// interpolated during operations.
208 
209  void wranglePointAttribute(GA_Attribute *attrib);
210  void wranglePointAttribute(
211  const GA_AttributeFilter &filter);
212 
213  void wrangleVertexAttribute(GA_Attribute *attrib);
214  void wrangleVertexAttribute(
215  const GA_AttributeFilter &filter);
216 
217  void wranglePrimitiveAttribute(GA_Attribute *attrib);
218  void wranglePrimitiveAttribute(
219  const GA_AttributeFilter &filter);
220 
221  /// Clear the list of wrangled point/vertex/primitive attributes.
222 
224  { deleteAttribRefMap(myPointAttrRefMap); }
225 
227  { deleteAttribRefMap(myVertexAttrRefMap); }
228 
230  { deleteAttribRefMap(myPrimitiveAttrRefMap); }
231 
232  /// Temporarily enable or disable all wrangling of point/vertex/primitive
233  /// attributes initiated by calling wranglePointAttributes(), etc.
234 
236  { myPointWranglingEnabled = enable;}
237 
239  { myVertexWranglingEnabled = enable;}
240 
242  { myPrimitiveWranglingEnabled = enable;}
243 
244  /// Return the polygon to which the hedge belongs.
247  { return geo_hedge::hedgePrimitive(myGdp, h); }
248 
249  // Hedge to poly and poly to first hedge
251  { return vertexPrimitive(srcVertex(h)); }
252 
254  { return GEO_Hedge(polyFirst(poly)); }
255 
256  // Returns true if vtx is the source vertex of a valid half-edge.
259  { return GAisValid(vtx)
260  && GAisValid(symNext(vtx)); }
261 
262  /// Check whether a hedge is valid. A half-edge is valid if it is
263  /// belongs to a closed polygon in the group on which the interface
264  /// is constructed or is the result of the manipulation of such hedges.
267  { return isValidHedgeSrcVertex(srcVertex(h)); }
268 
270  bool isValid(GEO_Hedge h) const
271  { return isValidHedge(h); }
272 
273  /// returns true of h is the *primary* hedge in its equivalence class.
274  /// Each equivalence class of hedges at any time has a unique primary
275  /// hedge. This is used for example to enumerate over all edges in the
276  /// detail (as opposed to over all hedges).
278  bool isPrimary(GEO_Hedge h) const
279  { return !isSecondary(srcVertex(h)); }
280 
281  /// Returns the source vertex of the hedge.
284  { return geo_hedge::srcVertex(h); }
285 
286  /// Returns the destination vertex of the hedge.
289  { return geo_hedge::dstVertex(*this, h); }
290 
291  /// Returns the vertex preceding the source of the hedge in its polygon.
294  { return geo_hedge::preSrcVertex(*this, h); }
295 
296  /// Returns the vertex succeeding the destination of the hedge.
299  { return geo_hedge::postDstVertex(*this, h); }
300 
301  /// Returns the point to which the source vertex is wired.
304  { return geo_hedge::srcPoint(myGdp, h); }
305 
306  /// Returns the point to which the destination vertex is wired.
309  { return geo_hedge::dstPoint(*this, h); }
310 
311  /// Returns the point to which the preSrcVertex(h) is wired.
312  /// @see: preSrcVertex()
315  { return geo_hedge::preSrcPoint(*this, h); }
316 
317  /// Returns the point to which the postDstVertex(h) is wired.
318  /// @see: postDstVertex()
321  { return geo_hedge::postDstPoint(*this, h); }
322 
323  /// Returns the next hedge (hedge whose source is the destination of the
324  /// parameter hedge) in its polygon.
325 
328  { return geo_hedge::nextPrimitiveHedge(*this, h); }
329 
330  /// Quad-Edge/GQ alias for nextPrimitiveHedge().
333  { return nextPrimitiveHedge(h); }
334 
335  /// Returns the previous hedge (hedge whose destination is the source
336  /// of the parameter hedge) in its polygon.
339  { return geo_hedge::prevPrimitiveHedge(*this, h); }
340 
341  /// Quad-Edge/GQ alias for prevPrimitiveHedge().
344  { return prevPrimitiveHedge(h); }
345 
346  /// Returns the hedge other than the parameter hedge in its polygon that
347  // has pt as an endpoint.
350  GA_Offset pt) const;
351 
352  /// Returns the "next" equivalent hedge to h:
353  /// two hedges are equivalent if either their source and destination points
354  /// are the same or the source point of each is the destination point of
355  /// the other. Calling nextEquivalentHedge() repeatedly returns back to the
356  /// original hedge. Thus to check if hedge h is manifold hedge one can
357  // check that:
358  // nextEquivalentHedge(h) != h
359  // && nextEquivalentHedge(nextEquivalentHedge(h)) == h.
360  // Note that this only verifies that there are two distinct hedges in the
361  // class but does not verify that they are oriented oppositely.
364  { return GEO_Hedge(symNext(srcVertex(h))); }
365 
366  /// Quad-Edge/GQ alias for nextEquivalentHedge().
369  { return nextEquivalentHedge(h); }
370 
371  /// Returns the primary hedge equivalent to the argument hedge.
374  { return GEO_Hedge(findPrimary(srcVertex(h))); }
375 
376  /// Alias for primaryEquivalentHedge().
379  { return primaryEquivalentHedge(h); }
380 
381  /// Arbitrarily-Ordered Scan Methods:
382  /// These methods scan over all edge/hedges incident to a point in an
383  /// arbitrary order. NB. This order may be different in different
384  /// executions of the code or across different platforms.
385 
386  /// Returns a first incident hedge to a point. Together with
387  /// nextIncidentHedge, one can enumerate circularly over all hedges
388  /// incident to a point. A hedge is incident to a point if one of its
389  /// endpoints is that point.
392  { return geo_hedge::firstIncidentHedge(*this, p); }
393 
396  { return geo_hedge::nextIncidentHedge(*this, h, p); }
397 
398  /// Similar to first/nextIncidentHedge but stops only at the primary
399  /// hedge in each equivalence class of hedges involved.
402  { return geo_hedge::firstIncidentEdge(*this, p); }
403 
406  { return geo_hedge::nextIncidentEdge(*this, h, p); }
407 
408  /// Similar to first/nextIncidentHedge but using only outgoing hedges.
409  /// Note that nextOutgoingHedge does not need the parameter p anymore.
412  { return geo_hedge::firstOutgoingHedge(*this, p); }
413 
416  { return geo_hedge::nextOutgoingHedge(*this, h); }
417 
418  /// Similar to first/nextIncidentHedge but using only incoming hedges.
419  /// Note that nextOutgoingHedge does not need the parameter p anymore.
422  { return geo_hedge::firstIncomingHedge(*this, p); }
423 
426  { return geo_hedge::nextIncomingHedge(*this, h); }
427 
428  /// Manifold Scan Methods:
429 
430  /// A "manifold scan" around a point moves from one incoming (resp outgoing
431  /// hedge incident to a point to the next in counterclockwise order as
432  /// long as the hedge in question is a manifold hedge (i.h. it is
433  /// equivalent to exactly one other hedge oriented oppositely).
434 
435  /// Returns the first hedge with the same destination point as the argument
436  /// hedge that is reachable from it through a counterclockwise manifold
437  /// scan around the destination point.
438  /// Returns the argument hedge itself if either:
439  /// 1) it is already the first such hedge, or
440  /// 2) its source is an interior point of a manifold,
441  /// ie. a counterclockwise scan does a full circle.
444 
445 
446  /// Quad-Edge/GQ alias:
449  { return firstManifoldIncomingHedge(h); }
450  /// Returns the previous hedge with the same dst as h in a
451  /// counterclockwise manifold scan, returns GEO_INVALID_HEDGE if no
452  /// such hedge exists.
453  ///
454  /// NOTE: This is equivalent to dprev() operation in Quad-Edge
455  /// terminology, which is also used in GQ.
458 
459  /// Quad-Edge/GQ alias:
462  { return prevManifoldIncomingHedge(h); }
463 
464  /// Returns the next hedge with the same dst as h in a counterclockwise
465  /// manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
466  ///
467  /// NOTE: This is equivalent to dnext() operation in Quad-Edge
468  /// terminology, which is also used in GQ.
471 
472  /// Quad-Edge/GQ alias:
475  { return nextManifoldIncomingHedge(h); }
476 
477  /// Similar to firstManifoldIncomingHedge but finds the first hedge with
478  /// the same src as h in a counterclockwise scan from h.
481 
482  /// Quad-Edge/GQ alias:
485  { return firstManifoldOutgoingHedge(h); }
486 
487  /// Returns the previous hedge with the same src as h in a counterclockwise
488  // manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
489  ///
490  /// NOTE: This is equivalent to oprev() operation in Quad-Edge
491  /// terminology, which is also used in GQ or equivalently lnext(sym()).
494 
495  /// Alias for prevManifoldOutgoingHedge, equivalent to lnext(sym()).
498  { return prevManifoldOutgoingHedge(h); }
499 
500  /// Returns the next hedge with the same src as h in a counterclockwise
501  /// manifold scan, returns GEO_INVALID_HEDGE if no such hedge exists.
502  ///
503  /// NOTE: This is equivalent to onext() operation in Quad-Edge
504  /// terminology, which is also used in GQ or equivalently sym(lprev()).
507 
508  /// Alias for nextManifoldOutgoingHedge, equivalent to sym(lprev()).
511  { return nextManifoldOutgoingHedge(h); }
512 
513  /// Returns true if the hedge h is a manifold hedge, if accept_bd is
514  /// false, this means that the equivalence class of h consists of
515  /// exactly two hedges oriented oppositely. If accept_bd is true, then
516  /// the equivalence class of h can also consist of a single (boundary)
517  /// half-edge.
520  bool accept_bd = false) const;
521 
522  /// Returns true if the hedge h is a boundary hedge, i.e. if its
523  /// equivalence class is singleton.
526  { return geo_hedge::isBoundaryHedge(*this, h); }
527 
528  /// Returns true if the hedge h is a bridge hedge, i.e. if is a
529  /// manifold hedge and its other equivalent hedge belongs to the
530  /// same primitive as h does.
533  { return geo_hedge::isBridgeHedge(*this, h); }
534 
535  /// Returns true if h1 and h2 are equivalent hedges with opposite
536  /// orientation.
538  bool areOpposite(GEO_Hedge h1, GEO_Hedge h2) const
539  { return geo_hedge::areOpposite(*this, h1, h2); }
540 
541  /// Returns true if h1 and h2 are equivalent hedges.
543  bool areEquivalent(GEO_Hedge h1, GEO_Hedge h2) const
544  { return geo_hedge::areEquivalent(*this, h1, h2); }
545 
546  /// Returns the number of hedges in the equivalence class of h.
549  { return geo_hedge::numEquivalentHedges(*this, h); }
550 
551  /// Returns the number if *edges* incident to a point (equivalent hedges
552  /// count as 1).
555  { return geo_hedge::numIncidentEdges(*this, pt); }
556 
557  /// Returns the number of distinct *hedges* incident to pt
560  { return geo_hedge::numIncidentHedges(*this, pt); }
561 
562  /// Find a hedge with the given endpoints or return GEO_INVLAID_HEDGE
565  GA_Offset p1) const;
566 
567  /// Rotate h forward, assuming h is an interior manifold hedge (equivalent
568  /// to exactly one other hedge f oppositely oriented. This is not checked
569  /// and the topology may be corrupted if rotate is applied to non-manifold
570  /// or boundary edges. Returns the resulting hedge which happens to be
571  /// equal to h (The input hedge will be the hedge that rotates (same src
572  /// vertex) and the same holds for the equivalent edge of h.
573  ///
574  /// ------>------> ------>------>
575  /// ^ |^ | ^ /7|
576  /// | || | | // |
577  /// | h || | ===> | h // |
578  /// | || | | // |
579  /// | v| v | // v
580  /// <------<------ |L/<---<------
581  ///
582  /// Note that this operation is precisely an edge flip if the two
583  /// primitives involved are triangles.
584  ///
585  /// Note also that the half-edges associated with the flipped edge are
586  /// *NOT* identified with those of any pre-existing edge with the same
587  /// endpoints. This deviates from the convention taken by poly interface
588  /// but is very useful when pinching of a surface is temporarily needed
589  /// as is the case with many algorithms. Method isFlippable() can be used
590  /// to determine such a scenario beforehand.
591  GEO_Hedge rotateForward(GEO_Hedge h);
592 
593  /// Complete reverse of rotateForward (all the point, vertex, and
594  /// primitive offsets are restored). When the incident primitives are
595  /// triangles, rotating forward or backward result in the same edge but
596  /// they are not exactly identical. In particular, two consecutive flips
597  /// on the same edge will reverse the orientation of the edge.
598  GEO_Hedge rotateBackward(GEO_Hedge h);
599 
600  /// Returns true if h can be flipped without the result overlapping an
601  /// existing hedge. In other words, h is flippable if its endpoints are
602  /// not endpoints of an existing edge in the geometry before the flip that
603  /// is not equivalent to h.
604  bool isFlippable(GEO_Hedge h) const;
605 
606  /// Flip h (provided that h is shared between two triangles) and is
607  /// flippable. Returns the resulting (flipped) hedge (equal to h) or
608  /// GEO_INVALID_HEDGE if h is not flippable.
610 
611  /// unflip is the reverse of a flip. Doing a flip followed by an unflip
612  /// should result in the same mesh with the same vertex/point/primtive
613  /// offsets and indices (but the vertices within primitives may shift).
614  GEO_Hedge unflip(GEO_Hedge h);
615 
616  /// Returns true if the hedge h is contractible, i.e. contracting h does
617  /// not force a a non-trivial (separating) cycle to collapse. A separating
618  /// cycle is a closed sequence of edges that if removed (together with
619  /// their incident geometry elements) the number of connected components
620  // increases. Contracting a non-contractible edge will split geometry into
621  /// multiple components.
622  bool isContractible(GEO_Hedge h) const;
623 
624  /// Contracts h.
625  /// @parameter on_dst, if true, causes the src point to move to the
626  /// position of the dst point. Otherwise, the dst point
627  /// is moved to the src point's position.
628  /// @parameter ratio, if in [0.0 .. 1.0], places the point of contraction
629  /// in a convex combination with biases ratio and
630  /// 1.0 - ratio from src and dst (or the other way around
631  /// if on_dst is false) respectively.
632 
633  // The internal flag distinguishes two different policies on whether
634  // the neighbouring triangles to the ones being destroyed as the result of
635  // the contraction of the edge inherit any of the half-edges of the latter
636  // triangles. If internal is set to true, the half-edge preceding or
637  // following each collapsing half-edge (depending on whether on_dst is true
638  // or not and whether the half-edge is oriented similarly to h or not) is
639  // inherited by the neighbouring triangle at the other half-edge sharing
640  // a vertex with the one being collapsed. If internal is false though,
641  // all half-edges of the destroyed triangles are destroyed and the others
642  // survive and are unified in the expected manner. If `copy_vtx_attribs`
643  // is set to true, then requested vertex attributes of the surviving end
644  // of h (its destination if `on_dst` is true and its source otherwise)
645  // will be copied to all surviving vertices wired to the destroyed point.
646 
647  GA_Offset contract(GEO_Hedge h, bool on_dst = true,
648  fpreal ratio = -1.0,
649  bool check_contractible = true,
650  bool internal = true,
651  bool destroy_released_point = true,
652  bool copy_vtx_attribs = false);
653 
654  /// Splits the hedge h and its incident polygon (assumed to be a triangle,
655  /// although it doesn't fail if it isn't).
656  /// @parameter ratio determines the position of the new point at which the
657  /// hedge is split.
658  /// @parameter and_equivalent if true also splits all other hedges
659  /// equivalent to h at the same point.
660  /// @parameter pt is an optional point offset assumed to be located in
661  // the correct position (as given by ratio). This allows
662  // the caller to reuse points already created.
664  bool and_equivalent = true,
666 
667  /// Inserts a point in the middle of a hedge and divides into two hedges.
668  ///
669  /// @parameter ratio determines the position of the new point at which the
670  /// hedge is split.
671  /// @parameter and_equivalent if true also divides all other hedges
672  /// equivalent to h at the same point.
673  /// @parameter pt is an optional point offset assumed to be located in
674  // the correct position (as given by ratio). This allows
675  // the caller to reuse points already created.
677  bool and_equivalent = true,
679 
680  /// Break a polygon into two polygons by dividing it along a diagonal.
681  /// The hedges starting from h_keep and ending before h_drop are kept in
682  /// the current polygon while the hedges starting at h_drop and ending
683  /// before h_keep end up in the new polygon. The returned hedge will be
684  /// one added to the original polygon corresponding to the cut diagonal.
685  /// NB. h_keep and h_drop *must* belong to the same polygon and cannot
686  /// be the same or consecutive hedges.
687  GEO_Hedge divide(GA_Offset poly, GEO_Hedge h_keep,
688  GEO_Hedge h_drop);
689 
690  /// Split a polygon at its barycenter, or a given point. If the point
691  /// is not given, then the position of the created point is set to the
692  /// barycenter of the polygon.
695 
696  /// Triangualtes a polygon.
697 
698  template <typename T = fpreal32>
699  exint triangulate(GA_Offset poly,
700  UT_Vector3T<T> *sym_ctr = nullptr,
701  GA_ROHandleT< UT_Vector3T<T> > pos_handle
703  GEO_Hedge start_hedge = GEO_INVALID_HEDGE,
704  UT_Array< UT_Vector3T<T> > *pos3 = nullptr,
705  UT_Array< UT_Vector2T<T> > *pos2 = nullptr,
706  UT_Triangulate::WorkBuffer *wb = nullptr,
707  UT_IntArray *tris = nullptr);
708 
709  template <typename S, typename T = fpreal32>
710  exint triangulate(const S &&polys,
711  UT_Vector3T<T> *sym_ctr = nullptr,
712  GA_ROHandleT< UT_Vector3T<T> > pos_handle
714 
715  // Deletes the *star* of a point. The star of a point in a polygonal
716  // complex consists of all edges and polygons incident to that point.
717  // So, deleting the star of an internal point on a manifold should leave
718  // a hole behind. If the cap_link is true, the hole is capped
719  // (if possible) with a new polygon. For this be possible the point *must*
720  // be an internal manifold point. If capping is possible then one of
721  // the polygons previously incident to pt can be specified as cap_poly
722  // to extend and become the patching polygon. If this polygon is not
723  // specified or is not actually incident to pt, then a new polygon will
724  // be created. The point pt itself is destroyed if destroy_pt is true.
725 
726  void deletePointStar(GA_Offset pt, bool cap_hole = true,
727  GA_Offset cap_poly = GA_INVALID_OFFSET,
728  bool destroy_pt = true);
729 
730 
731  // Dissolve the edge represented by h. The edge to be dissolved must be
732  // an interior manifold edge with consistent winding in the two polygons
733  // sharing it. Return value is true if h is dissovled and false if
734  // the dissolving has failed.
735  bool dissolve(GEO_Hedge h);
736 
737  void wireVertexPoint(GA_Offset vtx, GA_Offset pt,
738  bool rewire_hedges = true);
739 
740  /// Basic polygon manipulation methods. You should use these instead of
741  /// those offered by GEO_PrimPoly while dealing with softened polys.
742 
743  GA_Offset appendPoly();
744 
746  bool isValidPoly(GA_Offset poly) const
747  { return GAisValid(poly)
748  && GAisValid(polyFirst(poly)); }
749 
750  void destroyPoly(GA_Offset poly, bool and_pts = false);
751 
752  GA_Offset appendVertex(GA_Offset poly, GA_Offset pt,
753  bool relink_hedges = true);
754 
755  GA_Offset insertVertex(GA_Offset poly, GA_Offset pt,
756  GA_Offset before = GA_INVALID_OFFSET,
757  bool relink_hedges = true);
758 
759  GA_Offset stealVertex(GA_Offset poly, GA_Offset vtx,
760  GA_Offset insert_before = GA_INVALID_OFFSET,
761  bool relink_hedges = true);
762 
763  int deleteVertex(GA_Offset vtx, bool relink_hedges = true);
764 
765  int vertexCount(GA_Offset poly) const;
766 
767  GA_Detail *getDetail() const { return myGdp; }
768 
769  bool softValidate() const;
770  bool validate() const;
771 
773  GA_Offset prevPrimVertex(GA_Offset v) const;
774 
776  GA_Offset nextPrimVertex(GA_Offset v) const;
777 
779  void getAdjacentPrimVertices(GA_Offset v, GA_Offset &vprev,
780  GA_Offset &vnext) const;
781 
782  void dumpHedge(GA_Offset vtx);
784  { dumpHedge(srcVertex(h)); }
785 
786  // For a given polygon offset controlled by this interface, polyFirst()
787  // returns the first vertex in the circular list of vertices of that
788  // polygon. If a polygon is not modified by the interface this will be
789  // the first vertex of the input polygon. Also, when the polygon is
790  // hardened, this will be its first vertex.
791 
793  GA_Offset polyFirst(GA_Offset poly) const;
794 
795  // Given a vertex of a polygon, returns the next vertex in its
796  // circular list of vertices.
799  { return GA_Offset(myNextPolyHedge->getLink(v)); }
800 
801  // Given a vertex of a polygon, returns the previous vertex in its
802  // circular list of vertices.
805  { return GA_Offset(myPrevPolyHedge->getLink(v)); }
806 
807  UT_Vector3 calcBarycenter(GA_Offset poly) const;
808 
809  struct PolyFilter
810  {
811  explicit PolyFilter(const GEO_PolyInterface &pi) : myPI(pi) { }
812  bool operator()(GA_Offset off) const
813  { return myPI.isValidPoly(off); }
814 
815  private:
816  const GEO_PolyInterface &myPI;
817  };
819 
820  struct HedgeFilter
821  {
822  explicit HedgeFilter(const GEO_PolyInterface &pi) :
823  myPI(pi) { }
824 
825  bool operator()(GA_Offset off) const
826  { return myPI.isValidHedge(GEO_Hedge(off)); }
827 
828  private:
829  const GEO_PolyInterface &myPI;
830  };
832 
834  {
835  explicit PrimaryHedgeFilter(const GEO_PolyInterface &pi) :
836  myPI(pi) { }
837 
838  bool operator()(GA_Offset off) const
839  { return myPI.isValidHedge(GEO_Hedge(off))
840  && myPI.isPrimary(GEO_Hedge(off)); }
841  private:
842  const GEO_PolyInterface &myPI;
843  };
845 
846  PolyRange polys(const GA_PrimitiveGroup *g = nullptr,
847  bool complement = false) const;
848  HedgeRange hedges(const GA_VertexGroup *g = nullptr) const;
849  PrimaryHedgeRange primaryHedges(const GA_VertexGroup *g = nullptr) const;
850 
852  {
853  explicit PolyCirculator(const GEO_PolyInterface &pi) :
854  myPI(pi) { }
855 
857  { return myPI.polyNext(off); }
858  private:
859  const GEO_PolyInterface &myPI;
860  };
861 
863 
864  /// Returns the hedges around a polygon as a PolyCycle.
866  { return PolyCycle(PolyCirculator(*this),
867  polyFirst(poly)); }
868 
869 private:
870 
871  /// Get or set previous or next hedge in the circular list of hedges
872  /// equivalent (sym) to the one with source v.
873  ///
874  /// The equivalence class of a hedge consists of all hedges whose two
875  /// endpoints coincide with those of the hedge in question (although they
876  /// may be reversely paired). By *endpoints* of a hedge we mean the two
877  /// points into which the tail and head vertex of a hedge are respectively
878  /// wired.
879  /// @note Starting with any valid hedge, repeated calls to prevSymHedge
880  /// or enxtSym traverses all hedges to the original one and
881  /// ultimately wraps around.
882 
884  GA_Topology &topology() const { return myGdp->getTopology(); }
885 
887  void symPrev(GA_Offset v, GA_Offset w);
888 
890  GA_Offset symPrev(GA_Offset v) const
891  { return myPrevSymHedge->getLink(v); }
892 
894  void symNext(GA_Offset v, GA_Offset w);
895 
897  GA_Offset symNext(GA_Offset v) const;
898 
899 
900  /// Form a singleton half-edge equivalence class over src_vtx. Clearly,
901  /// the formed half-edge will be primary.
902  /// NB. This should be the ONLY way of creating a valid half-edge outside
903  /// of the buildHedgeTopology().
904 
906  void symLoop(GA_Offset src_vtx);
907 
908 
910  bool isPrimary(GA_Offset v) const
911  { return !isSecondary(v); }
913  bool isSecondary(GA_Offset v) const;
914 
916  void makePrimary(GA_Offset v);
917 
919  void makeSecondary(GA_Offset v);
920 
921  /// returns the primary hedge in the equivalence class of a given hedge
922  GA_Offset findPrimary(GA_Offset vtx) const;
923 
924  /// Methods for finding hedges along the boundary of a given polygon.
926  void polyFirst(GA_Offset poly, GA_Offset v);
927 
928 
930  void polyPrev(GA_Offset v, GA_Offset w)
931  { myPrevPolyHedge->setLink(v, w); }
932 
934  void polyNext(GA_Offset v, GA_Offset w)
935  { myNextPolyHedge->setLink(v, w); }
936 
938  void polyLoop(GA_Offset src_vtx);
939 
941  void getAdjacentBoundaryVertices(GA_Offset vtx,
942  GA_Offset &prev_vtx,
943  GA_Offset &next_vtx) const;
944 
946  bool isHard(GA_Offset v) const
947  { return !isSoft(v); }
949  bool isSoft(GA_Offset poly) const;
950 
952  void makeHard(GA_Offset poly);
953 
955  void makeSoft(GA_Offset poly);
956 
958  GA_Offset vertexPoint(GA_Offset vtx) const
959  { return myGdp->vertexPoint(vtx); }
960 
962  void vertexPoint(GA_Offset vtx, GA_Offset pt)
963  { topology().wireVertexPoint(vtx, pt); }
964 
966  GA_Offset vertexToNextVertex(GA_Offset vtx) const
967  { return myGdp->vertexToNextVertex(vtx); }
968 
970  GA_Offset pointVertex(GA_Offset vtx) const
971  { return myGdp->pointVertex(vtx); }
972 
974  GA_Offset vertexPrimitive(GA_Offset vtx) const
975  { return myGdp->vertexPrimitive(vtx); }
976 
978  void vertexPrimitive(GA_Offset vtx, GA_Offset p)
979  { topology().wireVertexPrimitive(vtx, p); }
980 
981  void symUnlink(GA_Offset tailv);
982 
983  void symLink(GA_Offset src_vtx,
984  GA_Offset into_vtx = GA_INVALID_OFFSET);
985 
986  GA_Offset symFind(GA_Offset src_vtx, GA_Offset dst_vtx);
987 
988  /// This should remain the only possible way of assigning GA_INVALID_OFFSET
989  /// to a specific hedge sym next, effectively rendering it invalid. That's
990  /// aside from the default attrbute value being the same.
991 
993  void invalidateHedge(GA_Offset src_vtx)
994  {
995  myNextSymHedge->setLink(src_vtx,
997 
998  void symRelink(GA_Offset src_vtx,
999  GA_Offset into_src_vtx = GA_INVALID_OFFSET);
1000 
1001  void symRelinkJoint(GA_Offset vtx, GA_Offset prev_into,
1002  GA_Offset vtx_into);
1003 
1004  void symRelinkJoint(GA_Offset vtx);
1005  void wireVertexPointAndRelinkHedges(GA_Offset vtx,
1006  GA_Offset pt, GA_Offset prev_into_src_vtx,
1007  GA_Offset next_into_src_vtx);
1008 
1009  // Deprecated, kept for a couple of unported methods.
1011  GEO_PrimPoly *hedgePrimPoly(GEO_Hedge h) const;
1012 
1013  const GEO_PrimPoly *getPrimPoly(GA_Offset primoff) const;
1014  GEO_PrimPoly *getPrimPoly(GA_Offset primoff);
1015 
1016  typedef std::pair<GA_Offset, GA_Offset> OffsetPair;
1017  typedef UT_Array<OffsetPair> OffsetPairArray;
1018 
1019  void buildHedgeTopology(const GA_PrimitiveGroup *polys);
1020 
1021  void linkPointIncidentHedges(GA_Offset pt,
1022  OffsetPairArray &pairs_local,
1023  const GA_PrimitiveGroup *polys,
1024  UT_IntArray &index_cache);
1025 
1026  void polyLink(GA_Offset vtx, GA_Offset prev,
1027  GA_Offset next);
1028 
1029  void polyUnlink(GA_Offset vtx,
1030  bool release_from_poly = true);
1031 
1032  bool verifyPoly(GA_Offset poly) const;
1033 
1035  void copyVtxAttribs(GA_Offset dst, GA_Offset src);
1036 
1038  void lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1039  GA_Offset src1, fpreal bias);
1041  void copyPtAttribs(GA_Offset dst, GA_Offset src);
1042 
1044  void lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1045  GA_Offset src1, fpreal bias);
1047  void copyPrimAttribs(GA_Offset dst, GA_Offset src);
1048 
1050  void lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1051  GA_Offset src1, fpreal bias);
1052 
1053  GEO_Hedge splitHedgeSrc(GEO_Hedge h, GA_Offset pt,
1054  bool local_split_edge_link,
1055  GA_Offset link0 = GA_INVALID_OFFSET,
1056  GA_Offset link1 = GA_INVALID_OFFSET,
1057  fpreal lerp_ratio = 0.5);
1058 
1059  GEO_Hedge splitHedgeDst(GEO_Hedge h, GA_Offset pt,
1060  bool local_split_edge_link,
1061  GA_Offset link0 = GA_INVALID_OFFSET,
1062  GA_Offset link1 = GA_INVALID_OFFSET,
1063  fpreal lerp_ratio = 0.5);
1064 
1065 
1066  void deleteAttribRefMap(GA_AttributeRefMap *&r)
1067  { delete r; r = nullptr; }
1068 
1069  bool contractHedgeSrc(GEO_Hedge h);
1070  bool contractHedgeDst(GEO_Hedge h);
1071 
1072 
1074  bool compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1075  UT_IntArray &index_cache);
1076 
1077  void createTopologyAttributes();
1078 
1079  GA_Detail *myGdp = nullptr;
1080 
1081  GA_ATITopology *myPrevSymHedge = nullptr;
1082  GA_ATITopology *myNextSymHedge = nullptr;
1083  GA_ATITopology *myPrevPolyHedge = nullptr;
1084  GA_ATITopology *myNextPolyHedge = nullptr;
1085  GA_ATITopology *myFirstPolyHedge = nullptr;
1086 
1087  GA_AttributeRefMap *myPointAttrRefMap = nullptr;
1088  GA_AttributeRefMap *myVertexAttrRefMap = nullptr;
1089  GA_AttributeRefMap *myPrimitiveAttrRefMap = nullptr;
1090 
1091  GA_OffsetArray myTempOffsetArray1;
1092  GA_OffsetArray myTempOffsetArray2;
1093 
1094  bool myPointWranglingEnabled = true;
1095  bool myVertexWranglingEnabled = true;
1096  bool myPrimitiveWranglingEnabled = true;
1097 };
1098 
1099 void
1100 GEO_PolyInterface::symPrev(GA_Offset v, GA_Offset w)
1101 {
1102  if (!GAisValid(w))
1103  myPrevSymHedge->setLink(v, GA_INVALID_OFFSET);
1104  else
1105  myPrevSymHedge->setLink(v, w);
1106 }
1107 
1108 void
1109 GEO_PolyInterface::symNext(GA_Offset v, GA_Offset w)
1110 {
1113 
1114  bool secondary = isSecondary(v);
1115  auto raw = RawLinkType(w);
1116  if (secondary)
1117  raw = setLinkFlag(raw);
1118  myNextSymHedge->setLink(v, GA_Offset(raw));
1119 }
1120 
1121 GA_Offset
1122 GEO_PolyInterface::symNext(GA_Offset v) const
1123 {
1124  GA_Offset off = myNextSymHedge->getLink(v);
1125  if (!GAisValid(off))
1126  return GA_INVALID_OFFSET;
1127 
1128  // Clear the secondary bit if set!
1129  return GA_Offset(clearLinkFlag(RawLinkType(off)));
1130 }
1131 
1132 void
1134 {
1135  if (!GAisValid(v))
1136  myFirstPolyHedge->setLink(poly, GA_INVALID_OFFSET);
1137  else
1138  {
1139  // Preserve the soft bit!
1140  bool soft = isSoft(poly);
1141  auto raw = RawLinkType(v);
1142  if (soft)
1143  raw = setLinkFlag(raw);
1144  myFirstPolyHedge->setLink(poly, GA_Offset(raw));
1145  }
1146 }
1147 
1148 GA_Offset
1150 {
1151  GA_Offset v = myFirstPolyHedge->getLink(poly);
1152  if (!GAisValid(v))
1153  return v;
1154 
1155  // Clear the soft bit if set!
1156  return GA_Offset(clearLinkFlag(RawLinkType(v)));
1157 }
1158 
1159 bool
1160 GEO_PolyInterface::isSecondary(GA_Offset v) const
1161 {
1162  return getLinkFlag(RawLinkType(myNextSymHedge->getLink(v)));
1163 }
1164 
1165 void
1166 GEO_PolyInterface::makeSecondary(GA_Offset v)
1167 {
1168  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1169  myNextSymHedge->setLink(v, GA_Offset(setLinkFlag(raw)));
1170 }
1171 
1172 void
1173 GEO_PolyInterface::makePrimary(GA_Offset v)
1174 {
1175  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1176  myNextSymHedge->setLink(v, GA_Offset(clearLinkFlag(raw)));
1177 }
1178 
1179 bool
1180 GEO_PolyInterface::isSoft(GA_Offset poly) const
1181 {
1182  return getLinkFlag(RawLinkType(myFirstPolyHedge->getLink(poly)));
1183 }
1184 
1185 void
1186 GEO_PolyInterface::makeSoft(GA_Offset poly)
1187 {
1188  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1189  myFirstPolyHedge->setLink(poly, GA_Offset(setLinkFlag(raw)));
1190 }
1191 
1192 void
1193 GEO_PolyInterface::makeHard(GA_Offset poly)
1194 {
1195  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1196  myFirstPolyHedge->setLink(poly, GA_Offset(clearLinkFlag(raw)));
1197 }
1198 
1199 void
1200 GEO_PolyInterface::symLoop(GA_Offset src_vtx)
1201 {
1202  myNextSymHedge->setLink(src_vtx, src_vtx);
1203  myPrevSymHedge->setLink(src_vtx, src_vtx);
1204 
1205  // NB. Semantically, symLoop() must make src_vtx primary. Since our
1206  // implementation of making primary works by removing the secondary
1207  // bit which in this case has never been set anyway, we skip this.
1208  //
1209  // makePrimary(src_vtx);
1210 }
1211 
1212 void
1213 GEO_PolyInterface::polyLoop(GA_Offset src_vtx)
1214 {
1215  polyPrev(src_vtx, src_vtx);
1216  polyNext(src_vtx, src_vtx);
1217 }
1218 
1219 GA_Offset
1221 {
1222  return polyPrev(v);
1223 }
1224 
1225 GA_Offset
1227 {
1228  return polyNext(v);
1229 }
1230 
1231 void
1233  GA_Offset &vnext) const
1234 {
1235  // TODO: we probably should get rid of this one.
1236  vprev = polyPrev(v);
1237  vnext = polyNext(v);
1238 }
1239 
1240 GEO_Hedge
1242 {
1243  return geo_hedge::firstManifoldIncomingHedge(*this, h);
1244 }
1245 
1246 GEO_Hedge
1248 {
1249  return geo_hedge::prevManifoldIncomingHedge(*this, h);
1250 }
1251 
1252 GEO_Hedge
1254 {
1255  return geo_hedge::nextManifoldIncomingHedge(*this, h);
1256 }
1257 
1258 GEO_Hedge
1260 {
1261  return geo_hedge::firstManifoldOutgoingHedge(*this, h);
1262 }
1263 
1264 GEO_Hedge
1266 {
1267  return geo_hedge::nextManifoldOutgoingHedge(*this, h);
1268 }
1269 
1270 GEO_Hedge
1272 {
1273  return geo_hedge::prevManifoldOutgoingHedge(*this, h);
1274 }
1275 
1276 GEO_Hedge
1278 {
1279  return geo_hedge::findHedgeWithEndpoints(*this, p0, p1);
1280 }
1281 
1282 bool
1284 {
1285  return geo_hedge::isManifoldHedge(*this, h, accept_bd);
1286 }
1287 
1288 GEO_Hedge
1290 {
1291  return geo_hedge::otherPrimitiveHedgeAtPoint(*this, h, pt);
1292 }
1293 
1294 GEO_PrimPoly *
1295 GEO_PolyInterface::hedgePrimPoly(GEO_Hedge h) const
1296 {
1297  GA_Offset primoff = myGdp->vertexPrimitive(srcVertex(h));
1298  return static_cast<GEO_PrimPoly *>(myGdp->getPrimitive(primoff));
1299 }
1300 
1301 void
1302 GEO_PolyInterface::copyVtxAttribs(GA_Offset dst, GA_Offset src)
1303 {
1304  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1305  myVertexAttrRefMap->copyValue(GA_ATTRIB_VERTEX, dst,
1306  GA_ATTRIB_VERTEX, src);
1307 }
1308 
1309 void
1310 GEO_PolyInterface::lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1311  GA_Offset src1, fpreal b)
1312 {
1313  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1314  myVertexAttrRefMap->lerpValue(GA_ATTRIB_VERTEX, dst,
1315  GA_ATTRIB_VERTEX, src0, src1, b);
1316 }
1317 
1318 void
1319 GEO_PolyInterface::copyPtAttribs(GA_Offset dst, GA_Offset src)
1320 {
1321  if (myPointAttrRefMap && myPointWranglingEnabled)
1322  myPointAttrRefMap->copyValue(GA_ATTRIB_POINT, dst,
1323  GA_ATTRIB_POINT, src);
1324 }
1325 
1326 void
1327 GEO_PolyInterface::lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1328  GA_Offset src1, fpreal b)
1329 {
1330  if (myPointAttrRefMap && myPointWranglingEnabled)
1331  myPointAttrRefMap->lerpValue(GA_ATTRIB_POINT, dst,
1332  GA_ATTRIB_POINT, src0, src1, b);
1333 }
1334 
1335 void
1336 GEO_PolyInterface::copyPrimAttribs(GA_Offset dst, GA_Offset src)
1337 {
1338  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1339  myPrimitiveAttrRefMap->copyValue(GA_ATTRIB_PRIMITIVE, dst,
1340  GA_ATTRIB_PRIMITIVE, src);
1341 }
1342 
1343 void
1344 GEO_PolyInterface::lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1345  GA_Offset src1, fpreal b)
1346 {
1347  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1348  myPrimitiveAttrRefMap->lerpValue(GA_ATTRIB_PRIMITIVE, dst,
1349  GA_ATTRIB_PRIMITIVE, src0, src1, b);
1350 }
1351 
1352 bool
1353 GEO_PolyInterface::compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1354  UT_IntArray &index_cache)
1355 {
1356  if (v0 == v1)
1357  return false;
1358 
1359  if (index_cache(v0) < 0 || index_cache(v1) < 0)
1360  {
1361  GA_Offset poly = vertexPrimitive(v0);
1362  GA_Offset v_first = polyFirst(poly);
1363  if (!GAisValid(v_first))
1364  return false;
1365 
1366  int i = 0;
1367  GA_Offset v = v_first;
1368  do
1369  {
1370  index_cache(v) = i++;
1371  v = polyNext(v);
1372  } while (v != v_first);
1373  }
1374 
1375  UT_ASSERT_P(index_cache(v0) >= 0 && index_cache(v1) >= 0);
1376  return index_cache(v0) < index_cache(v1);
1377 }
1378 
1379 
1380 #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:190
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:380
GLenum src
Definition: glew.h:2410
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
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:645
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.
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
const GLdouble * v
Definition: glew.h:1391
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:145
bool operator()(GA_Offset off) const
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:231
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:674
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:637
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
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:2981
SYS_FORCE_INLINE GA_Offset postDstVertex(T &iface, GEO_Hedge e)
Definition: GEO_Hedge.h:218
void OIIO_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
SYS_FORCE_INLINE bool isBoundaryHedge(GEO_Hedge h) const
unsigned long long uint64
Definition: SYS_Types.h:112
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:
GLclampf f
Definition: glew.h:3499
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:120
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().
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:134
GT_API const UT_StringHolder topology
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)
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1890
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.
GLenum GLenum dst
Definition: glew.h:2410
#define GEO_API
Definition: GEO_API.h:14
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
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8011
GLfloat bias
Definition: glew.h:10274
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)
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
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.
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
GLfloat GLfloat p
Definition: glew.h:16321
Cycle(const CIRCULATOR &f, GA_Offset base)
SYS_FORCE_INLINE GA_Offset vertexPrimitive(GA_Offset vertex) const
Definition: GA_Detail.h:488
double fpreal
Definition: SYS_Types.h:276
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)
ImageBuf OIIO_API flip(const ImageBuf &src, ROI roi={}, int nthreads=0)
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.
GLdouble GLdouble GLdouble r
Definition: glew.h:1406
SYS_FORCE_INLINE GEO_Hedge prevManifoldIncomingHedge(GEO_Hedge h) const
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.
GLfloat v0
Definition: glew.h:1848
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:95
Iterator end() const
GEO_Hedge firstIncidentHedge(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:383
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
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)
GLboolean enable
Definition: glew.h:2745
GLfloat GLfloat v1
Definition: glew.h:1852
PrimaryHedgeFilter(const GEO_PolyInterface &pi)
FilteredRange(const FILTER &f, const GA_Range &r)
std::enable_if<!std::is_integral< T >::value, T >::type divide(const T &a, const T &b)
Definition: Composite.h:156
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
GLboolean GLboolean g
Definition: glew.h:9477
SYS_FORCE_INLINE GEO_Hedge nextPrimitiveHedge(GEO_Hedge h) const
unsigned int uint32
Definition: SYS_Types.h:40
SYS_FORCE_INLINE void setLink(GA_Offset ai, GA_Offset v)