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.
349  GEO_Hedge otherPrimitiveHedgeAtPoint(GEO_Hedge h,
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 
772  void dumpHedge(GA_Offset vtx);
774  { dumpHedge(srcVertex(h)); }
775 
778  { return myGdp->vertexPoint(vtx); }
779 
782  { return myGdp->vertexToNextVertex(vtx); }
783 
786  { return myGdp->pointVertex(vtx); }
787 
790  { return myGdp->vertexPrimitive(vtx); }
791 
792 
793  // For a given polygon offset controlled by this interface, polyFirst()
794  // returns the first vertex in the circular list of vertices of that
795  // polygon. If a polygon is not modified by the interface this will be
796  // the first vertex of the input polygon. Also, when the polygon is
797  // hardened, this will be its first vertex.
798 
800  GA_Offset polyFirst(GA_Offset poly) const;
801 
802  // Given a vertex of a polygon, returns the next vertex in its
803  // circular list of vertices.
806  { return GA_Offset(myNextPolyHedge->getLink(v)); }
807 
810  { vprev = polyPrev(vtx); return polyNext(vtx); }
811 
812 
813  // Given a vertex of a polygon, returns the previous vertex in its
814  // circular list of vertices.
817  { return GA_Offset(myPrevPolyHedge->getLink(v)); }
818 
819  UT_Vector3 calcBarycenter(GA_Offset poly) const;
820 
821  struct PolyFilter
822  {
823  explicit PolyFilter(const GEO_PolyInterface &pi) : myPI(pi) { }
824  bool operator()(GA_Offset off) const
825  { return myPI.isValidPoly(off); }
826 
827  private:
828  const GEO_PolyInterface &myPI;
829  };
831 
832  struct HedgeFilter
833  {
834  explicit HedgeFilter(const GEO_PolyInterface &pi) :
835  myPI(pi) { }
836 
837  bool operator()(GA_Offset off) const
838  { return myPI.isValidHedge(GEO_Hedge(off)); }
839 
840  private:
841  const GEO_PolyInterface &myPI;
842  };
844 
846  {
847  explicit PrimaryHedgeFilter(const GEO_PolyInterface &pi) :
848  myPI(pi) { }
849 
850  bool operator()(GA_Offset off) const
851  { return myPI.isValidHedge(GEO_Hedge(off))
852  && myPI.isPrimary(GEO_Hedge(off)); }
853  private:
854  const GEO_PolyInterface &myPI;
855  };
857 
858  PolyRange polys(const GA_PrimitiveGroup *g = nullptr,
859  bool complement = false) const;
860  HedgeRange hedges(const GA_VertexGroup *g = nullptr) const;
861  PrimaryHedgeRange primaryHedges(const GA_VertexGroup *g = nullptr) const;
862 
864  {
865  explicit PolyCirculator(const GEO_PolyInterface &pi) :
866  myPI(pi) { }
867 
869  { return myPI.polyNext(off); }
870  private:
871  const GEO_PolyInterface &myPI;
872  };
873 
875 
876  /// Returns the hedges around a polygon as a PolyCycle.
878  { return PolyCycle(PolyCirculator(*this),
879  polyFirst(poly)); }
880 
881 private:
882 
883  /// Get or set previous or next hedge in the circular list of hedges
884  /// equivalent (sym) to the one with source v.
885  ///
886  /// The equivalence class of a hedge consists of all hedges whose two
887  /// endpoints coincide with those of the hedge in question (although they
888  /// may be reversely paired). By *endpoints* of a hedge we mean the two
889  /// points into which the tail and head vertex of a hedge are respectively
890  /// wired.
891  /// @note Starting with any valid hedge, repeated calls to prevSymHedge
892  /// or enxtSym traverses all hedges to the original one and
893  /// ultimately wraps around.
894 
896  GA_Topology &topology() const { return myGdp->getTopology(); }
897 
899  void symPrev(GA_Offset v, GA_Offset w);
900 
902  GA_Offset symPrev(GA_Offset v) const
903  { return myPrevSymHedge->getLink(v); }
904 
906  void symNext(GA_Offset v, GA_Offset w);
907 
909  GA_Offset symNext(GA_Offset v) const;
910 
911 
912  /// Form a singleton half-edge equivalence class over src_vtx. Clearly,
913  /// the formed half-edge will be primary.
914  /// NB. This should be the ONLY way of creating a valid half-edge outside
915  /// of the buildHedgeTopology().
916 
918  void symLoop(GA_Offset src_vtx);
919 
920 
922  bool isPrimary(GA_Offset v) const
923  { return !isSecondary(v); }
925  bool isSecondary(GA_Offset v) const;
926 
928  void makePrimary(GA_Offset v);
929 
931  void makeSecondary(GA_Offset v);
932 
933  /// returns the primary hedge in the equivalence class of a given hedge
934  GA_Offset findPrimary(GA_Offset vtx) const;
935 
936  /// Methods for finding hedges along the boundary of a given polygon.
938  void polyFirst(GA_Offset poly, GA_Offset v);
939 
940 
942  void polyPrev(GA_Offset v, GA_Offset w)
943  { myPrevPolyHedge->setLink(v, w); }
944 
946  void polyNext(GA_Offset v, GA_Offset w)
947  { myNextPolyHedge->setLink(v, w); }
948 
950  void polyLoop(GA_Offset src_vtx);
951 
952 
953  // Simulated sym() function without use of any half-edge interfaces.
954  // (used for verifications)
955  static GA_Offset hedgeToNextHedgeSlow(GA_Offset src_vtx,
956  const GA_Detail *gdp);
957 
958  // Look-up the neighbour two vertices from the polygon vertex list.
959  // (used for verification). NB. Polygons must be hardened!
961  static void getAdjacentPolyVertices(const GA_Detail *gdp,
962  GA_Offset vtx,
963  GA_Offset &prev_vtx,
964  GA_Offset &next_vtx);
965 
967  bool isHard(GA_Offset v) const
968  { return !isSoft(v); }
970  bool isSoft(GA_Offset poly) const;
971 
973  void makeHard(GA_Offset poly);
974 
976  void makeSoft(GA_Offset poly);
977 
979  void vertexPoint(GA_Offset vtx, GA_Offset pt)
980  { topology().wireVertexPoint(vtx, pt); }
981 
983  void vertexPrimitive(GA_Offset vtx, GA_Offset p)
984  { topology().wireVertexPrimitive(vtx, p); }
985 
986  void symUnlink(GA_Offset tailv);
987 
988  void symLink(GA_Offset src_vtx,
989  GA_Offset into_vtx = GA_INVALID_OFFSET);
990 
991  GA_Offset symFind(GA_Offset src_vtx, GA_Offset dst_vtx);
992 
993  /// This should remain the only possible way of assigning GA_INVALID_OFFSET
994  /// to a specific hedge sym next, effectively rendering it invalid. That's
995  /// aside from the default attrbute value being the same.
996 
998  void invalidateHedge(GA_Offset src_vtx)
999  {
1000  myNextSymHedge->setLink(src_vtx,
1001  GA_INVALID_OFFSET); }
1002 
1003  void symRelink(GA_Offset src_vtx,
1004  GA_Offset into_src_vtx = GA_INVALID_OFFSET);
1005 
1006  void symRelinkJoint(GA_Offset vtx, GA_Offset prev_into,
1007  GA_Offset vtx_into);
1008 
1009  void symRelinkJoint(GA_Offset vtx);
1010  void wireVertexPointAndRelinkHedges(GA_Offset vtx,
1011  GA_Offset pt, GA_Offset prev_into_src_vtx,
1012  GA_Offset next_into_src_vtx);
1013 
1014  // Deprecated, kept for a couple of unported methods.
1016  GEO_PrimPoly *hedgePrimPoly(GEO_Hedge h) const;
1017 
1018  const GEO_PrimPoly *getPrimPoly(GA_Offset primoff) const;
1019  GEO_PrimPoly *getPrimPoly(GA_Offset primoff);
1020 
1021  typedef std::pair<GA_Offset, GA_Offset> OffsetPair;
1022  typedef UT_Array<OffsetPair> OffsetPairArray;
1023 
1024  void buildHedgeTopology(const GA_PrimitiveGroup *polys);
1025 
1026  void linkPointIncidentHedges(GA_Offset pt,
1027  OffsetPairArray &pairs_local,
1028  const GA_PrimitiveGroup *polys,
1029  UT_IntArray &index_cache);
1030 
1031  void polyLink(GA_Offset vtx, GA_Offset prev,
1032  GA_Offset next);
1033 
1034  void polyUnlink(GA_Offset vtx,
1035  bool release_from_poly = true);
1036 
1037  bool verifyPoly(GA_Offset poly) const;
1038 
1040  void copyVtxAttribs(GA_Offset dst, GA_Offset src);
1041 
1043  void lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1044  GA_Offset src1, fpreal bias);
1046  void copyPtAttribs(GA_Offset dst, GA_Offset src);
1047 
1049  void lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1050  GA_Offset src1, fpreal bias);
1052  void copyPrimAttribs(GA_Offset dst, GA_Offset src);
1053 
1055  void lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1056  GA_Offset src1, fpreal bias);
1057 
1058  GEO_Hedge splitHedgeSrc(GEO_Hedge h, GA_Offset pt,
1059  bool local_split_edge_link,
1060  GA_Offset link0 = GA_INVALID_OFFSET,
1061  GA_Offset link1 = GA_INVALID_OFFSET,
1062  fpreal lerp_ratio = 0.5);
1063 
1064  GEO_Hedge splitHedgeDst(GEO_Hedge h, GA_Offset pt,
1065  bool local_split_edge_link,
1066  GA_Offset link0 = GA_INVALID_OFFSET,
1067  GA_Offset link1 = GA_INVALID_OFFSET,
1068  fpreal lerp_ratio = 0.5);
1069 
1070 
1071  void deleteAttribRefMap(GA_AttributeRefMap *&r)
1072  { delete r; r = nullptr; }
1073 
1074  bool contractHedgeSrc(GEO_Hedge h);
1075  bool contractHedgeDst(GEO_Hedge h);
1076 
1077 
1079  bool compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1080  UT_IntArray &index_cache);
1081 
1082  void createTopologyAttributes();
1083 
1084  GA_Detail *myGdp = nullptr;
1085 
1086  GA_ATITopology *myPrevSymHedge = nullptr;
1087  GA_ATITopology *myNextSymHedge = nullptr;
1088  GA_ATITopology *myPrevPolyHedge = nullptr;
1089  GA_ATITopology *myNextPolyHedge = nullptr;
1090  GA_ATITopology *myFirstPolyHedge = nullptr;
1091 
1092  GA_AttributeRefMap *myPointAttrRefMap = nullptr;
1093  GA_AttributeRefMap *myVertexAttrRefMap = nullptr;
1094  GA_AttributeRefMap *myPrimitiveAttrRefMap = nullptr;
1095 
1096  GA_OffsetArray myTempOffsetArray1;
1097  GA_OffsetArray myTempOffsetArray2;
1098 
1099  bool myPointWranglingEnabled = true;
1100  bool myVertexWranglingEnabled = true;
1101  bool myPrimitiveWranglingEnabled = true;
1102 };
1103 
1104 void
1105 GEO_PolyInterface::symPrev(GA_Offset v, GA_Offset w)
1106 {
1107  if (!GAisValid(w))
1108  myPrevSymHedge->setLink(v, GA_INVALID_OFFSET);
1109  else
1110  myPrevSymHedge->setLink(v, w);
1111 }
1112 
1113 void
1114 GEO_PolyInterface::symNext(GA_Offset v, GA_Offset w)
1115 {
1118 
1119  bool secondary = isSecondary(v);
1120  auto raw = RawLinkType(w);
1121  if (secondary)
1122  raw = setLinkFlag(raw);
1123  myNextSymHedge->setLink(v, GA_Offset(raw));
1124 }
1125 
1126 GA_Offset
1127 GEO_PolyInterface::symNext(GA_Offset v) const
1128 {
1129  GA_Offset off = myNextSymHedge->getLink(v);
1130  if (!GAisValid(off))
1131  return GA_INVALID_OFFSET;
1132 
1133  // Clear the secondary bit if set!
1134  return GA_Offset(clearLinkFlag(RawLinkType(off)));
1135 }
1136 
1137 void
1139 {
1140  if (!GAisValid(v))
1141  myFirstPolyHedge->setLink(poly, GA_INVALID_OFFSET);
1142  else
1143  {
1144  // Preserve the soft bit!
1145  bool soft = isSoft(poly);
1146  auto raw = RawLinkType(v);
1147  if (soft)
1148  raw = setLinkFlag(raw);
1149  myFirstPolyHedge->setLink(poly, GA_Offset(raw));
1150  }
1151 }
1152 
1153 GA_Offset
1155 {
1156  GA_Offset v = myFirstPolyHedge->getLink(poly);
1157  if (!GAisValid(v))
1158  return v;
1159 
1160  // Clear the soft bit if set!
1161  return GA_Offset(clearLinkFlag(RawLinkType(v)));
1162 }
1163 
1164 bool
1165 GEO_PolyInterface::isSecondary(GA_Offset v) const
1166 {
1167  return getLinkFlag(RawLinkType(myNextSymHedge->getLink(v)));
1168 }
1169 
1170 void
1171 GEO_PolyInterface::makeSecondary(GA_Offset v)
1172 {
1173  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1174  myNextSymHedge->setLink(v, GA_Offset(setLinkFlag(raw)));
1175 }
1176 
1177 void
1178 GEO_PolyInterface::makePrimary(GA_Offset v)
1179 {
1180  auto raw = RawLinkType(myNextSymHedge->getLink(v));
1181  myNextSymHedge->setLink(v, GA_Offset(clearLinkFlag(raw)));
1182 }
1183 
1184 bool
1185 GEO_PolyInterface::isSoft(GA_Offset poly) const
1186 {
1187  return getLinkFlag(RawLinkType(myFirstPolyHedge->getLink(poly)));
1188 }
1189 
1190 void
1191 GEO_PolyInterface::makeSoft(GA_Offset poly)
1192 {
1193  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1194  myFirstPolyHedge->setLink(poly, GA_Offset(setLinkFlag(raw)));
1195 }
1196 
1197 void
1198 GEO_PolyInterface::makeHard(GA_Offset poly)
1199 {
1200  auto raw = RawLinkType(myFirstPolyHedge->getLink(poly));
1201  myFirstPolyHedge->setLink(poly, GA_Offset(clearLinkFlag(raw)));
1202 }
1203 
1204 void
1205 GEO_PolyInterface::symLoop(GA_Offset src_vtx)
1206 {
1207  myNextSymHedge->setLink(src_vtx, src_vtx);
1208  myPrevSymHedge->setLink(src_vtx, src_vtx);
1209 
1210  // NB. Semantically, symLoop() must make src_vtx primary. Since our
1211  // implementation of making primary works by removing the secondary
1212  // bit which in this case has never been set anyway, we skip this.
1213  //
1214  // makePrimary(src_vtx);
1215 }
1216 
1217 void
1218 GEO_PolyInterface::polyLoop(GA_Offset src_vtx)
1219 {
1220  polyPrev(src_vtx, src_vtx);
1221  polyNext(src_vtx, src_vtx);
1222 }
1223 
1224 GEO_Hedge
1226 {
1227  return geo_hedge::firstManifoldIncomingHedge(*this, h);
1228 }
1229 
1230 GEO_Hedge
1232 {
1233  return geo_hedge::prevManifoldIncomingHedge(*this, h);
1234 }
1235 
1236 GEO_Hedge
1238 {
1239  return geo_hedge::nextManifoldIncomingHedge(*this, h);
1240 }
1241 
1242 GEO_Hedge
1244 {
1245  return geo_hedge::firstManifoldOutgoingHedge(*this, h);
1246 }
1247 
1248 GEO_Hedge
1250 {
1251  return geo_hedge::nextManifoldOutgoingHedge(*this, h);
1252 }
1253 
1254 GEO_Hedge
1256 {
1257  return geo_hedge::prevManifoldOutgoingHedge(*this, h);
1258 }
1259 
1260 GEO_Hedge
1262 {
1263  return geo_hedge::findHedgeWithEndpoints(*this, p0, p1);
1264 }
1265 
1266 bool
1268 {
1269  return geo_hedge::isManifoldHedge(*this, h, accept_bd);
1270 }
1271 
1272 GEO_Hedge
1274 {
1275  return geo_hedge::coincidentPolyHedge(*this, h, pt);
1276 }
1277 
1278 GEO_PrimPoly *
1279 GEO_PolyInterface::hedgePrimPoly(GEO_Hedge h) const
1280 {
1281  GA_Offset primoff = myGdp->vertexPrimitive(srcVertex(h));
1282  return static_cast<GEO_PrimPoly *>(myGdp->getPrimitive(primoff));
1283 }
1284 
1285 void
1286 GEO_PolyInterface::copyVtxAttribs(GA_Offset dst, GA_Offset src)
1287 {
1288  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1289  myVertexAttrRefMap->copyValue(GA_ATTRIB_VERTEX, dst,
1290  GA_ATTRIB_VERTEX, src);
1291 }
1292 
1293 void
1294 GEO_PolyInterface::lerpVtxAttribs(GA_Offset dst, GA_Offset src0,
1295  GA_Offset src1, fpreal b)
1296 {
1297  if (myVertexAttrRefMap && myVertexWranglingEnabled)
1298  myVertexAttrRefMap->lerpValue(GA_ATTRIB_VERTEX, dst,
1299  GA_ATTRIB_VERTEX, src0, src1, b);
1300 }
1301 
1302 void
1303 GEO_PolyInterface::copyPtAttribs(GA_Offset dst, GA_Offset src)
1304 {
1305  if (myPointAttrRefMap && myPointWranglingEnabled)
1306  myPointAttrRefMap->copyValue(GA_ATTRIB_POINT, dst,
1307  GA_ATTRIB_POINT, src);
1308 }
1309 
1310 void
1311 GEO_PolyInterface::lerpPtAttribs(GA_Offset dst, GA_Offset src0,
1312  GA_Offset src1, fpreal b)
1313 {
1314  if (myPointAttrRefMap && myPointWranglingEnabled)
1315  myPointAttrRefMap->lerpValue(GA_ATTRIB_POINT, dst,
1316  GA_ATTRIB_POINT, src0, src1, b);
1317 }
1318 
1319 void
1320 GEO_PolyInterface::copyPrimAttribs(GA_Offset dst, GA_Offset src)
1321 {
1322  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1323  myPrimitiveAttrRefMap->copyValue(GA_ATTRIB_PRIMITIVE, dst,
1324  GA_ATTRIB_PRIMITIVE, src);
1325 }
1326 
1327 void
1328 GEO_PolyInterface::lerpPrimAttribs(GA_Offset dst, GA_Offset src0,
1329  GA_Offset src1, fpreal b)
1330 {
1331  if (myPrimitiveAttrRefMap && myPrimitiveWranglingEnabled)
1332  myPrimitiveAttrRefMap->lerpValue(GA_ATTRIB_PRIMITIVE, dst,
1333  GA_ATTRIB_PRIMITIVE, src0, src1, b);
1334 }
1335 
1336 bool
1337 GEO_PolyInterface::compareOrderInPoly(GA_Offset v0, GA_Offset v1,
1338  UT_IntArray &index_cache)
1339 {
1340  if (v0 == v1)
1341  return false;
1342 
1343  if (index_cache(v0) < 0 || index_cache(v1) < 0)
1344  {
1345  GA_Offset poly = vertexPrimitive(v0);
1346  GA_Offset v_first = polyFirst(poly);
1347  if (!GAisValid(v_first))
1348  return false;
1349 
1350  int i = 0;
1351  GA_Offset v = v_first;
1352  do
1353  {
1354  index_cache(v) = i++;
1355  v = polyNext(v);
1356  } while (v != v_first);
1357  }
1358 
1359  UT_ASSERT_P(index_cache(v0) >= 0 && index_cache(v1) >= 0);
1360  return index_cache(v0) < index_cache(v1);
1361 }
1362 
1363 
1364 #endif
GEO_Hedge prevManifoldOutgoingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:629
SYS_FORCE_INLINE GEO_Hedge lnext(GEO_Hedge h) const
Quad-Edge/GQ alias for nextPrimitiveHedge().
SYS_FORCE_INLINE GEO_Hedge coincidentPolyHedge(T &iface, GEO_Hedge h, GA_Offset pt)
Definition: GEO_Hedge.h:284
GEO_Hedge firstOutgoingHedge(T &iface, GA_Offset point)
Definition: GEO_Hedge.h:511
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
SYS_FORCE_INLINE GA_Offset srcPoint(const GA_Detail *gdp, GEO_Hedge h)
Definition: GEO_Hedge.h:186
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
SYS_FORCE_INLINE GA_Offset postDstPoint(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:260
SYS_FORCE_INLINE GEO_Hedge onext(GEO_Hedge h) const
Alias for nextManifoldOutgoingHedge, equivalent to sym(lprev()).
GEO_Hedge firstManifoldOutgoingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:675
GA_Size numIncidentEdges(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:823
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.
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
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 GA_Offset postDstVertex(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:231
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:
GA_Size numIncidentHedges(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:841
Iterator begin() const
bool GAisValid(GA_Size v)
Definition: GA_Types.h:645
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
GA_Offset srcVertex(GEO_Hedge)
Definition: GEO_Hedge.h:179
GEO_Hedge nextIncomingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:576
SYS_FORCE_INLINE GEO_Hedge nextPrimitiveHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:268
GEO_Hedge nextManifoldOutgoingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:613
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 dstPoint(GEO_Hedge h) const
Returns the point to which the destination vertex is wired.
SYS_FORCE_INLINE const GA_Primitive * hedgePrimitive(const GA_Detail *gdp, GEO_Hedge h)
Definition: GEO_Hedge.h:200
SYS_FORCE_INLINE GEO_Hedge firstIncidentEdge(GA_Offset p) const
SYS_FORCE_INLINE GA_Offset preSrcPoint(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:252
const GLdouble * v
Definition: glew.h:1391
SYS_FORCE_INLINE GA_Offset preSrcVertex(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:223
bool isBridgeHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:316
#define GEO_INVALID_HEDGE
An invalid hedge is sometimes returned if an operation is unsuccessful.
Definition: GEO_Hedge.h:32
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 h)
Definition: GEO_Hedge.h:660
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 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()).
SYS_FORCE_INLINE GA_Offset vertexToNextVertex(GA_Offset vtx) const
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:2981
void OIIO_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
SYS_FORCE_INLINE GA_Offset vertexPoint(GA_Offset vtx) const
GEO_Hedge firstManifoldIncomingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:690
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 GEO_Hedge ofirst(GEO_Hedge h) const
Quad-Edge/GQ alias:
GLclampf f
Definition: glew.h:3499
SYS_FORCE_INLINE GA_Offset pointVertex(GA_Offset vtx) const
SYS_FORCE_INLINE bool areEquivalent(GEO_Hedge h1, GEO_Hedge h2) const
Returns true if h1 and h2 are equivalent hedges.
SYS_FORCE_INLINE bool areOpposite(T &iface, GEO_Hedge h1, GEO_Hedge h2)
Definition: GEO_Hedge.h:373
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().
SYS_FORCE_INLINE GA_Size numEquivalentHedges(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:357
#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 bool areOpposite(GEO_Hedge h1, GEO_Hedge h2) const
A handle to simplify manipulation of multiple attributes.
GEO_Hedge nextIncidentEdge(T &iface, GEO_Hedge h, GA_Offset point)
Definition: GEO_Hedge.h:494
SYS_FORCE_INLINE GEO_Hedge firstManifoldOutgoingHedge(GEO_Hedge h) const
GEO_Hedge nextIncidentHedge(T &iface, GEO_Hedge h, GA_Offset pt)
Definition: GEO_Hedge.h:413
GA_Detail * getDetail() const
GEO_Hedge firstIncomingHedge(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:558
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)
bool operator!=(const Iterator &other)
void enablePrimitiveWrangling(bool enable)
bool operator()(GA_Offset off) const
Iterator end() const
SYS_FORCE_INLINE GA_Offset dstVertex(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:215
SYS_FORCE_INLINE GA_Size numEquivalentHedges(GEO_Hedge h) const
Returns the number of hedges in the equivalence class of h.
SYS_FORCE_INLINE RawLinkType setLinkFlag(RawLinkType i)
SYS_FORCE_INLINE GEO_Hedge firstOutgoingHedge(GA_Offset p) const
SYS_FORCE_INLINE bool isManifoldHedge(T &iface, GEO_Hedge h, bool accept_bd)
Definition: GEO_Hedge.h:341
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
GEO_Hedge nextOutgoingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:525
bool operator!=(const Iterator &other)
GEO_Hedge prevManifoldIncomingHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:646
SYS_FORCE_INLINE GA_Offset polyNext(GA_Offset vtx, GA_Offset &vprev) const
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:803
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)
Iterator(const FILTER &f, const GA_Range &r)
GEO_Hedge firstIncidentEdge(T &iface, GA_Offset pt)
Definition: GEO_Hedge.h:474
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
GA_Offset hedgePoly(GEO_Hedge h) const
Iterator & operator++()
SYS_FORCE_INLINE bool areEquivalent(T &iface, GEO_Hedge h1, GEO_Hedge h2)
Definition: GEO_Hedge.h:298
SYS_FORCE_INLINE GEO_Hedge nextIncidentEdge(GEO_Hedge h, GA_Offset p) const
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:392
SYS_FORCE_INLINE GEO_Hedge nextManifoldIncomingHedge(GEO_Hedge h) const
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
SYS_FORCE_INLINE GA_Offset vertexPrimitive(GA_Offset vtx) const
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.
ITERTYPE operator*() const
SYS_FORCE_INLINE GEO_Hedge prevPrimitiveHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:276
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
SYS_FORCE_INLINE GA_Offset dstPoint(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:244
unsigned int uint32
Definition: SYS_Types.h:40
SYS_FORCE_INLINE bool isBoundaryHedge(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:309
SYS_FORCE_INLINE void setLink(GA_Offset ai, GA_Offset v)