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