HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_PathFinder.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: GU_PathFinder.h
7  *
8  * COMMENTS:
9  * Finds paths of various specifications between various element types
10  * in polygon meshes.
11  */
12 
13 #ifndef __GU_PathFinder__
14 #define __GU_PathFinder__
15 
16 #include "GU_API.h"
17 #include "GU_PathHedge.h"
18 
19 #include <GA/GA_Edge.h>
20 #include <GA/GA_EdgeGroup.h>
21 #include <GA/GA_ElementGroup.h>
22 #include <GA/GA_Group.h>
23 #include <GA/GA_Handle.h>
24 #include <GA/GA_Types.h>
25 #include <UT/UT_Array.h>
26 #include <UT/UT_BitArray.h>
27 #include <UT/UT_Map.h>
28 #include <UT/UT_PriorityQueue.h>
29 #include <UT/UT_Set.h>
30 #include <SYS/SYS_Inline.h>
31 #include <SYS/SYS_Types.h>
32 
33 class GA_Attribute;
34 class GA_Detail;
35 
36 
38 
40 
41 
43 {
44 public:
45  enum Type
46  {
47  QUAD_LEFT = 0,
52  ANY,
54  };
55 
56  enum Mask
57  {
58  ANY_MASK = 0,
64  };
65 
67 
68  GU_PathSHedge &operator()(int i) { return mySucc[i]; }
69  GU_PathSHedge operator()(int i) const { return mySucc[i]; }
70 
71  static
73  { return t < NUM_TYPES ? Mask(1 << t) : ANY_MASK; }
74 
75  void clear()
76  {
77  for (int i = 0; i < NUM_TYPES; ++i)
78  mySucc[i] = GU_PathSHedge();
79  }
80 
81 private:
82  GU_PathSHedge mySucc[NUM_TYPES];
83 };
84 
85 // Template parameter T is the cost class
86 
87 template <class T = gu_ShortestPathCost>
89 {
90 public:
91 
92  class PathEdge
93  {
94  public:
95  PathEdge() : mySHedge(GU_PathSHedge()), myPrev(GU_PathSHedge())
96  { }
97 
98  explicit
100  GU_PathSHedge prev = GU_PathSHedge()) :
101  mySHedge(sh), myPrev(prev) { myPathCost.zero(); }
102 
103  PathEdge(GU_PathSHedge sh, GU_PathSHedge prev, const T &cost) :
104  mySHedge(sh), myPrev(prev), myPathCost(cost) { }
105 
106  bool operator()(PathEdge &p1, PathEdge &p2) const
107  { return (p1.myPathCost > p2.myPathCost); }
108 
109  T getPathCost() { return myPathCost; }
110  GU_PathSHedge getSHedge() { return mySHedge; }
111  GU_PathSHedge getPrev() { return myPrev; }
112  bool hasPrev() { return myPrev.isValid(); }
113 
114  private:
115  GU_PathSHedge mySHedge, myPrev;
116  T myPathCost;
117  };
118 
119  using CostType = T;
120 
121 public:
122 
123  // If the uv_attrib parameter is passed, then the search takes place
124  // in UV space (boundaries, connectivity, etc follow the UVs).
125 
126  explicit GU_PathFinder(GU_PathHedge::Interface *dhip,
127  const GA_Attribute *uv_attrib = nullptr);
128 
129  // Paths are formed of *signed* half-edges, where the sign indicates
130  // whether the half-edge is being travelled from source to destination
131  // (positive) or the other way around (negative). Dual paths are sequences
132  // of edges (represented by half-edges) which are typically separated by
133  // polygons but may share endpoints. In specifying the start and end
134  // targets for path search, we used signed half-edges to indicate the
135  // direction of departure or arrival at the start or end edges
136  // respectively. In the dual path search, we only use positive half-edges
137  // since all that we care about are the start and end edges. Note that
138  // a search can specify multiple start and end (signed) half-edges. This
139  // is particularly used in implementing primitive, point, and vertex loops.
140 
141  // Set a start or ending half-edge for the next search. If and_equiv
142  // is set to true, then all equivalent half-edges to the given one are
143  // also added as possible start or end half-edges. Note that any generated
144  // path should follow the direction of one of these starting half-edges.
145  void setStartHedge(const GU_PathHedge& sh, bool and_equiv = true);
146  void setEndHedge(const GU_PathHedge& eh, bool and_equiv = true);
147 
148  // Set a start or end *signed* half-edge. Specifying the start or end
149  // half-edge this way can be used to free us from the actual direction of
150  // existing half-edges, particularly when the intended direction may not
151  // be realized by any half-edges, mostly notably in case of boundaries when
152  // we have a single half-edge. If and_reverse is set to true, the half-edge
153  // is added in both directions.
154  void setStartSHedge(const GU_PathSHedge& ssh,
155  bool and_reverse = false);
156  void setEndSHedge(const GU_PathSHedge& ssh,
157  bool and_reverse = false);
158 
159  // Specify the search start and end by points. These get translated to
160  // appropriate half-edges.
161  void setStartPoint(GA_Offset pt);
162  void setEndPoint(GA_Offset pt);
163 
164  // Specify the search start and end by vertices. These get translated to
165  // appropriate half-edges. Note that vertex path returns "representative"
166  // vertices between the two ends which are themselves treated as
167  // representatives of their respective points (or their respective island
168  // points if there's an active UV attribute).
169 
170  void setStartVertex(GA_Offset vtx);
171  void setEndVertex(GA_Offset vtx);
172 
173  // Set start and end primitives. These get translated to appropriate
174  // half-edges.
175  void setStartPrimitive(GA_Offset prim);
176  void setEndPrimitive(GA_Offset prim);
177 
178 
179  void clearStartSHedges();
180  void addStartSHedge(const GU_PathSHedge& sh,
181  bool and_reverse = false);
182 
183  void clearEndSHedges();
184  void addEndSHedge(const GU_PathSHedge& sh, bool and_reverse = false);
185 
186  // The main method to search for a the shortest path between a start
187  // signed half edge and an end one. The successor type mask allows
188  // to prioritize various types of successors and change the cost values
189  // and is utilized by the template parameter cost class.
190  T findPath(GU_SHedgeArray &path,
191  GU_EdgeSuccessor::Mask succ_type);
192 
193  // Find a dual path between a source and a destination half-edge.
194  T findDualPath(GU_SHedgeArray &path,
195  GU_EdgeSuccessor::Mask succ_type);
196 
197 
198  // Assign a group of points to be avoided by search paths.
200  { myAvoidPoints = grp; }
201 
202  // Assign a group of edges to be avoided by search paths.
204  { myAvoidEdges = grp; }
205 
206  // Assign a group of primitives to be avoided by search paths.
208  { myAvoidPrimitives = grp; }
209 
210  // Assign a group of vertices to be avoided by search paths.
212  { myAvoidVertices = grp; }
213 
214 
216  GA_EdgeGroup * edgegrp,
217  GA_VertexGroup *vtxgrp,
218  GA_PrimitiveGroup *primgrp)
219  {
220  if (ptgrp && ptgrp->entries())
221  avoidPoints(ptgrp);
222 
223  if (edgegrp && edgegrp->entries())
224  avoidEdges(edgegrp);
225 
226  if (vtxgrp && vtxgrp->entries())
227  avoidVertices(vtxgrp);
228 
229  if (primgrp && primgrp->entries())
230  avoidPrimitives(primgrp);
231  };
232 
234  {
235  avoidPoints(nullptr);
236  avoidEdges(nullptr);
237  avoidPrimitives(nullptr);
238  avoidVertices(nullptr);
239  }
240 
241  void setCollisionGroup(const GA_Group * group, bool exclude, bool strong)
242  {
243  myCollisionPoints = nullptr;
244  myCollisionPrimitives = nullptr;
245  myCollisionVertices = nullptr;
246  myCollisionEdges = nullptr;
247  myCollisionGroup = group;
248  myExcludeCollisionGroup = exclude;
249  myCollisionStrong = strong;
250  if (!group)
251  return;
252 
253  switch (group->classType())
254  {
255  case GA_GROUP_POINT:
256  myCollisionPoints = static_cast<const GA_PointGroup *>(group);
257  break;
258  case GA_GROUP_PRIMITIVE:
259  myCollisionPrimitives = static_cast<const GA_PrimitiveGroup *>(group);
260  break;
261  case GA_GROUP_VERTEX:
262  myCollisionVertices = static_cast<const GA_VertexGroup *>(group);
263  break;
264  case GA_GROUP_EDGE:
265  myCollisionEdges = static_cast<const GA_EdgeGroup *>(group);
266  break;
267  default:
268  break;
269  }
270  }
271 
272  // Reset partial search results. This clears the start and end elements,
273  // unless heap_only is set to true in which case only the partial search
274  // tree is cleared.
275  void reset(bool heap_only = false);
276 
277  const
279  { return myStartSHedges; }
280 
282  T &getBestCost(const GU_PathSHedge & sh);
283 
284  // Bypass cycles in the path or dual path.
285  void simplifyPath(GU_SHedgeArray &path);
286  void simplifyDualPath(GU_SHedgeArray &path);
287 
288  // Extend an open path on both ends by walking straight at regular
289  // quad junctions until the two ends meet or irregular points are reached.
290  // Returns true if the path changes and false otherwise.
291  bool extendPath(GU_SHedgeArray &path,
292  bool trim_crossing = true);
293 
294  // Extend an open dual path on both ends by walk over opposite quad edges
295  // until a closed edge ring is formed or a non-quad is reached.
296  bool extendDualPath(GU_SHedgeArray &path,
297  bool trim_crossing = true,
298  bool is_for_prim_loo = false);
299 
300  // Determine whether the start or end edges are boundary edges. When a
301  // UV attribute is given, this is determined with regard to that.
302 
303  bool isStartOnBoundary() { return myStartOnBoundary; }
304  bool isEndOnBoundary() { return myEndOnBoundary; }
305 
306 private:
307 
308  void dumpSHedge(const GU_PathSHedge & sh) const;
309 
311  void mark(const GU_PathSHedge & sh);
312 
314  bool isMarked(const GU_PathSHedge & sh);
315 
316  void initializeEdgeHeap();
317 
319  void setBestCost(const GU_PathSHedge& sh, const T &cost,
320  GU_PathSHedge prev_sh = GU_PathSHedge());
321 
323  GU_PathSHedge getPrev(const GU_PathSHedge & sh);
324 
326  bool hasPrev(const GU_PathSHedge & sh)
327  { return myDhip->isValidHedge(getPrev(sh).hedge()); }
328 
329  // Search for the destination point of the first signed half-edge in the
330  // path that matches pt and truncates the rest of the path. Returns true
331  // if the point is found or false otherwise.
332  bool trimPathAtPoint(GU_SHedgeArray &path, GA_Offset pt);
333 
334  // Search for a half-edge in the path incident to a primitive and truncates
335  // the rest of the path after that half-edge. Returns true if the primitive
336  // is found.
337  bool trimDualPathAtPrimitive(GU_SHedgeArray &path,
338  const GU_PathHedge & h);
339 
340  GA_Offset trimCrossingPaths(GU_SHedgeArray &w0,
341  GU_SHedgeArray &w1);
342 
343  GA_Offset trimCrossingDualPaths(GU_SHedgeArray &w0,
344  GU_SHedgeArray &w1);
345 
346 
347  // fills path with signed hedges from the optimal path found from a start
348  // signed hedge to esh.
349  void extractPath(const GU_PathSHedge & esh, GU_SHedgeArray &path);
350  void extractDualPath(const GU_PathSHedge &esh, GU_SHedgeArray &path);
351 
352  bool isStartSHedge(const GU_PathSHedge & sh);
353  bool isStartSHedgePrimary(const GU_PathSHedge &sh);
354 
355  bool isEndSHedge(const GU_PathSHedge & sh);
356  bool isEndSHedgePrimary(const GU_PathSHedge & sh);
357 
358  GU_PathSHedge findMarkedEndSHedge();
359  GU_PathSHedge findMarkedEndSHedgePrimary();
360 
361  // Some signed hedge helper methods
362 
363  GU_PathSHedge primary(const GU_PathSHedge &sh) const;
364  bool isPrimary(const GU_PathSHedge &sh) const;
365 
366  // Returns the right sign for h to have pt as it source.
368  int relativeSign(const GU_PathHedge & h, GA_Offset pt) const
369  { return pt == myDhip->srcPoint(h) ? 1 : -1; }
370 
371 
373  GA_Edge gaEdge(const GU_PathHedge & h) const
374  { return GA_Edge(myDhip->srcPoint(h),
375  myDhip->dstPoint(h)); }
376 
378  GA_Edge gaEdge(const GU_PathSHedge & sh) const;
379 
382  using SuccessorMask = GU_EdgeSuccessor::Mask;
383 
384  //const
385  GU_PathHedge::Interface *myDhip;
386 
387  const GA_Detail *myGdp;
388  GA_ROHandleV2 myUV;
389 
390  //These are very costly, may want to find some other way
391  UT_Set<GU_PathHedge> myPosMarked, myNegMarked;
392  UT_Map<GU_PathHedge, GU_PathSHedge> myPosPrev, myNegPrev;
393  UT_Map<GU_PathHedge, T> myPosCost, myNegCost;
394 
395  //Versions for polygons as an optimization
396  UT_BitArray myPolyPosMarked, myPolyNegMarked;
397  UT_Array<GU_PathSHedge> myPolyPosPrev, myPolyNegPrev;
398  UT_Array<T> myPolyPosCost, myPolyNegCost;
399 
400  EdgeHeap myEdgeHeap;
401 
402  GU_SHedgeArray myStartSHedges;
403  GU_SHedgeArray myStartSHedgePrimaries;
404  GU_SHedgeArray myEndSHedges;
405  GU_SHedgeArray myEndSHedgePrimaries;
406 
407  GU_PathSHedge myLastStartSHedge = GU_PathSHedge();
408  bool myLastStartSHedgeFlag = false;
409 
410  GU_PathHedge myLastStartHedge = GU_PathHedge();
411  bool myLastStartHedgeFlag = false;
412 
413  bool myStartOnBoundary = false;
414  bool myEndOnBoundary = false;
415 
416  GA_Offset myLastStartPoint = GA_INVALID_OFFSET;
417  GA_Offset myLastStartPrimitive = GA_INVALID_OFFSET;
418  GA_Offset myLastStartVertex = GA_INVALID_OFFSET;
419 
420 
421  GA_EdgeGroup *myAvoidEdges = nullptr;
422  GA_PointGroup *myAvoidPoints = nullptr;
423  GA_PrimitiveGroup *myAvoidPrimitives = nullptr;
424  GA_VertexGroup *myAvoidVertices = nullptr;
425 
426  //keep a pointer to each collision group type as an optimization
427  const GA_EdgeGroup *myCollisionEdges = nullptr;
428  const GA_PointGroup *myCollisionPoints = nullptr;
429  const GA_PrimitiveGroup *myCollisionPrimitives = nullptr;
430  const GA_VertexGroup *myCollisionVertices = nullptr;
431  //should be the same pointer as the non-null one above
432  const GA_Group * myCollisionGroup = nullptr;
433 
434  //when true will NOT allow paths containing collision group
435  //when false will constrain paths to collision group
436  bool myExcludeCollisionGroup = true;
437 
438  //when true will NOT allow paths along boundar
439  //when false will allow paths to partially contain collision group
440  bool myCollisionStrong = false;
441 
442  SuccessorMask mySuccessorTypeMask;
443 };
444 
446 {
447 public:
448  gu_ShortestPathCost() = default;
449  explicit gu_ShortestPathCost(fpreal l) : myLength(l) { }
450 
453  { myLength = dhip->length(sh.hedge()); }
454 
456  = default;
457 
459  void zero() { myLength = 0.0; }
460 
462  void unset() { myLength = -1.0; }
463 
465  bool isSet() { return myLength > -0.5; }
466 
468  bool operator>(const gu_ShortestPathCost &c) const
469  { return myLength > c.myLength; }
470 
473 
475  const
477  {
478  myLength += c.myLength;
479  return *this;
480  }
481 
483  static
485  const GU_PathSHedge & from_sh,
486  const GU_PathSHedge & to_sh,
487  const GU_EdgeSuccessor &exits)
488  {
489  return gu_ShortestPathCost(dhip->length(to_sh.hedge()));
490  }
491 
493  fpreal getLength() { return myLength; }
494 
495 private:
496  fpreal myLength = -1.0;
497 };
498 
500 {
501 public:
502  gu_EdgeLoopCost() = default;
504  GU_PathHedge::Interface *dhip) :
505  myPenalty(0),
506  myPathLength(dhip->length(sh.hedge())) { }
507 
508  gu_EdgeLoopCost(fpreal len, int bends) :
509  myPathLength(len), myPenalty(bends) { }
510 
512  myPathLength(c.myPathLength),
513  myPenalty(c.myPenalty) { }
514 
516  void zero()
517  {
518  myPathLength = 0.0;
519  myPenalty = 0;
520  }
521 
523  void unset() { myPathLength = -1.0; }
524 
526  bool isSet() { return myPathLength > -0.5; }
527 
529  bool operator>(const gu_EdgeLoopCost &c) const
530  {
531  if (myPenalty != c.myPenalty)
532  return myPenalty > c.myPenalty;
533 
534  return myPathLength > c.myPathLength;
535  }
536 
537  gu_EdgeLoopCost &operator=(const gu_EdgeLoopCost &c) = default;
538 
540  const
542  {
543  myPenalty += c.myPenalty;
544  myPathLength += c.myPathLength;
545  return *this;
546  }
547 
549  static
551  const GU_PathSHedge & from_sh,
552  const GU_PathSHedge & to_sh,
553  const GU_EdgeSuccessor &successors)
554  {
555  fpreal len = dhip->length(to_sh.hedge());
556 
557  GU_PathSHedge bd_succ = successors(GU_EdgeSuccessor::BOUNDARY);
558  if (bd_succ.isValid() && dhip->areEquivalent(to_sh, bd_succ))
559  return gu_EdgeLoopCost(len, 0);
560 
561  GU_PathSHedge sided_quad_succ = successors(GU_EdgeSuccessor::QUAD_LEFT);
562  if (!sided_quad_succ.isValid())
563  sided_quad_succ = successors(GU_EdgeSuccessor::QUAD_RIGHT);
564 
565  GU_PathSHedge opposite = successors(GU_EdgeSuccessor::QUAD_OPPOSITE);
566  if (!opposite.isValid())
567  opposite = successors(GU_EdgeSuccessor::OPPOSITE);
568 
569  bool to_sided_quad_succ = (sided_quad_succ.isValid() &&
570  dhip->areEquivalent(to_sh, sided_quad_succ));
571 
572  bool to_opposite = opposite.isValid() &&
573  dhip->areEquivalent(to_sh, opposite);
574 
575  if (to_sided_quad_succ)
576  return gu_EdgeLoopCost(len, 1);
577 
578  if (to_opposite)
579  return gu_EdgeLoopCost(len, 99);
580 
581  return gu_EdgeLoopCost(len, 100);
582  }
583 
585  fpreal getLength() { return myPathLength; }
586 
587 private:
588  fpreal myPathLength = -1.0;
589  int myPenalty = -1;
590 };
591 
592 
593 
595 {
596 public:
597  gu_EdgeRingCost() = default;
599  GU_PathHedge::Interface *dhip) :
600  myPenalty(0),
601  myPathLength(dhip->length(sh.hedge())) { }
602 
603  gu_EdgeRingCost(fpreal len, int bends) :
604  myPathLength(len), myPenalty(bends) { }
605 
606 
607  gu_EdgeRingCost(const gu_EdgeRingCost &c) = default;
608 
610  void zero()
611  {
612  myPathLength = 0.0;
613  myPenalty = 0;
614  }
615 
617  void unset() { myPathLength = -1.0; }
618 
620  bool isSet() { return myPathLength > -0.5; }
621 
623  bool operator>(const gu_EdgeRingCost &c) const
624  {
625  if (myPenalty != c.myPenalty)
626  return myPenalty > c.myPenalty;
627 
628  return myPathLength > c.myPathLength;
629  }
630 
631  gu_EdgeRingCost &operator=(const gu_EdgeRingCost &c) = default;
632 
634  const
636  {
637  myPenalty += c.myPenalty;
638  myPathLength += c.myPathLength;
639  return *this;
640  }
641 
643  static
645  const GU_PathSHedge& from_sh,
646  const GU_PathSHedge& to_sh,
647  const GU_EdgeSuccessor &successors)
648  {
649  fpreal len = dhip->length(to_sh.hedge());
650 
651  GU_PathSHedge bd_succ = successors(GU_EdgeSuccessor::BOUNDARY);
652  bool to_bd_succ = bd_succ.isValid() &&
653  dhip->areEquivalent(to_sh, bd_succ);
654 
655  if (to_bd_succ)
656  return gu_EdgeRingCost(len, 0);
657 
658  GU_PathSHedge sided_quad_succ = successors(GU_EdgeSuccessor::QUAD_LEFT);
659  if (!sided_quad_succ.isValid())
660  sided_quad_succ = successors(GU_EdgeSuccessor::QUAD_RIGHT);
661 
662  GU_PathSHedge opposite = successors(GU_EdgeSuccessor::QUAD_OPPOSITE);
663  if (!opposite.isValid())
664  opposite = successors(GU_EdgeSuccessor::OPPOSITE);
665 
666  bool to_sided_quad_succ = (sided_quad_succ.isValid() &&
667  dhip->areEquivalent(to_sh, sided_quad_succ));
668 
669  bool to_opposite = opposite.isValid() &&
670  dhip->areEquivalent(to_sh, opposite);
671 
672  if (to_sided_quad_succ)
673  return gu_EdgeRingCost(len, 1);
674 
675  if (to_opposite)
676  return gu_EdgeRingCost(len, 99);
677 
678  return gu_EdgeRingCost(len, 100);
679  }
680 
682  fpreal getLength() { return myPathLength; }
683 
684 private:
685  fpreal myPathLength = -1.0;
686  int myPenalty = -1;
687 };
688 
689 
690 // Marking of signed half-edges: Each half-edge in each orientation is
691 // given a flag which can be set or checked.
692 
693 template <class T>
694 void
696 {
697  if (myDhip->isHedgeValidPolygon(sh.hedge()))
698  {
699  if (sh.isPositive())
700  myPolyPosMarked.setBitFast(sh.hedge().v0(), true);
701  else
702  myPolyNegMarked.setBitFast(sh.hedge().v0(), true);
703  }
704  else
705  {
706  if (sh.isPositive())
707  myPosMarked.insert(sh.hedge());
708  else
709  myNegMarked.insert(sh.hedge());
710  }
711 }
712 
713 template <class T>
714 bool
716 {
717  if (myDhip->isHedgeValidPolygon(sh.hedge()))
718  {
719  if (sh.isPositive())
720  return myPolyPosMarked.getBitFast(sh.hedge().v0());
721  else
722  return myPolyNegMarked.getBitFast(sh.hedge().v0());
723  }
724  else
725  {
726  if (sh.isPositive())
727  return myPosMarked.contains(sh.hedge());
728  else
729  return myNegMarked.contains(sh.hedge());
730  }
731 }
732 
733 template <class T>
734 void
736  const T &cost,
737  GU_PathSHedge prev_sh)
738 {
739  if (myDhip->isHedgeValidPolygon(sh.hedge()))
740  {
741  if (sh.isPositive())
742  {
743  myPolyPosCost[sh.hedge().v0()] = cost;
744  myPolyPosPrev[sh.hedge().v0()] = prev_sh;
745  }
746  else
747  {
748  myPolyNegCost[sh.hedge().v0()] = cost;
749  myPolyNegPrev[sh.hedge().v0()] = prev_sh;
750  }
751  }
752  else
753  {
754  if (sh.isPositive())
755  {
756  myPosCost[sh.hedge()] = cost;
757  myPosPrev[sh.hedge()] = prev_sh;
758  }
759  else
760  {
761  myNegCost[sh.hedge()] = cost;
762  myNegPrev[sh.hedge()] = prev_sh;
763  }
764  }
765 }
766 
767 template <class T>
768 T &
770 {
771  if (myDhip->isHedgeValidPolygon(sh.hedge()))
772  {
773  if (sh.isPositive())
774  return myPolyPosCost[sh.hedge().v0()];
775  else
776  return myPolyNegCost[sh.hedge().v0()];
777  }
778  else
779  {
780  if (sh.isPositive())
781  return myPosCost[sh.hedge()];
782  else
783  return myNegCost[sh.hedge()];
784  }
785 }
786 
787 
788 template <class T>
791 {
792  if (myDhip->isHedgeValidPolygon(sh.hedge()))
793  {
794  if (sh.isPositive())
795  return myPolyPosPrev[sh.hedge().v0()];
796  else
797  return myPolyNegPrev[sh.hedge().v0()];
798  }
799  else
800  {
801  if (sh.isPositive())
802  return myPosPrev[sh.hedge()];
803  else
804  return myNegPrev[sh.hedge()];
805  }
806 }
807 
808 
809 template <class T>
810 GA_Edge
811 GU_PathFinder<T>::gaEdge(const GU_PathSHedge & sh) const
812 {
813  return sh.isNegative() ?
814  GA_Edge(myDhip->dstPoint(sh.hedge()), myDhip->srcPoint(sh.hedge())) :
815  GA_Edge(myDhip->srcPoint(sh.hedge()), myDhip->dstPoint(sh.hedge()));
816 }
817 
818 
819 
822 
824 {
825  GU_NO_SUCCESSOR, // No viable successors to take
826  GU_HIT_BOUNDARY, // Reached a boundary
827  GU_HIT_SELF, // Crossed itself
828  GU_COMPLETED // Closed the path
829 };
830 
832  const GA_ROHandleV2 &uvh,
834  GU_SHedgeArray &walk,
835  bool backward = false,
836  bool no_self_intersection = false,
837  bool include_ends = false,
838  const GA_PrimitiveGroup * avoid_prims = nullptr,
839  const GA_PointGroup * avoid_points = nullptr,
840  const GA_VertexGroup * avoid_vtx = nullptr,
841  const GA_EdgeGroup * avoid_edges = nullptr,
842  const GA_Group * collision_group = nullptr,
843  bool exclude_collision = true,
844  bool strong_rule = true);
845 
847  const GA_ROHandleV2 &uvh,
849  GU_SHedgeArray &walk,
850  bool backward = false,
851  bool no_self_intersection = false,
852  bool include_ends = false,
853  const GA_PrimitiveGroup * avoid_prims = nullptr,
854  const GA_PointGroup * avoid_points = nullptr,
855  const GA_VertexGroup * avoid_vtx = nullptr,
856  const GA_EdgeGroup * avoid_edges = nullptr,
857  const GA_Group * collision_group = nullptr,
858  bool exclude_collision = true,
859  bool strong_rule = true);
860 
861 #endif
862 
GU_WalkEndReason GU_API guDualEdgeWalk(GU_PathHedge::Interface *dhip, const GA_ROHandleV2 &uvh, GU_SHedgeArray &path, GU_SHedgeArray &walk, bool backward=false, bool no_self_intersection=false, bool include_ends=false, const GA_PrimitiveGroup *avoid_prims=nullptr, const GA_PointGroup *avoid_points=nullptr, const GA_VertexGroup *avoid_vtx=nullptr, const GA_EdgeGroup *avoid_edges=nullptr, const GA_Group *collision_group=nullptr, bool exclude_collision=true, bool strong_rule=true)
GA_Size entries() const override
Returns the number of edges in this group.
Definition: GA_EdgeGroup.h:309
SYS_FORCE_INLINE void unset()
SYS_FORCE_INLINE GA_Offset srcPoint(const GA_Detail *gdp, GEO_Hedge h)
Definition: GEO_Hedge.h:186
SYS_FORCE_INLINE bool isPositive() const
Definition: GU_PathHedge.h:388
void avoidGroups(GA_PointGroup *ptgrp, GA_EdgeGroup *edgegrp, GA_VertexGroup *vtxgrp, GA_PrimitiveGroup *primgrp)
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
const GU_SHedgeArray & getStartSHedges() const
SYS_FORCE_INLINE gu_ShortestPathCost & operator=(const gu_ShortestPathCost &c)=default
void avoidPoints(GA_PointGroup *grp)
GU_WalkEndReason GU_API guEdgeWalk(GU_PathHedge::Interface *dhip, const GA_ROHandleV2 &uvh, GU_SHedgeArray &path, GU_SHedgeArray &walk, bool backward=false, bool no_self_intersection=false, bool include_ends=false, const GA_PrimitiveGroup *avoid_prims=nullptr, const GA_PointGroup *avoid_points=nullptr, const GA_VertexGroup *avoid_vtx=nullptr, const GA_EdgeGroup *avoid_edges=nullptr, const GA_Group *collision_group=nullptr, bool exclude_collision=true, bool strong_rule=true)
SYS_FORCE_INLINE fpreal length(const GU_PathHedge &h) const
Definition: GU_PathHedge.h:257
GU_PathSHedge operator()(int i) const
Definition: GU_PathFinder.h:69
GA_Size entries() const overridefinal
Will return the number of primary elements.
SYS_FORCE_INLINE const gu_EdgeLoopCost & operator+=(const gu_EdgeLoopCost &c)
SYS_FORCE_INLINE void unset()
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
SYS_FORCE_INLINE fpreal getLength()
gu_EdgeLoopCost & operator=(const gu_EdgeLoopCost &c)=default
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
SYS_FORCE_INLINE fpreal getLength()
SYS_FORCE_INLINE bool isNegative() const
Definition: GU_PathHedge.h:391
PathEdge(GU_PathSHedge sh, GU_PathSHedge prev=GU_PathSHedge())
Definition: GU_PathFinder.h:99
SYS_FORCE_INLINE bool areEquivalent(const GU_PathHedge &h1, const GU_PathHedge &h2)
Definition: GU_PathHedge.h:182
SYS_FORCE_INLINE const GU_PathHedge & hedge() const
Definition: GU_PathHedge.h:377
GA_EdgeT< GA_Offset, false > GA_Edge
Definition: GA_Edge.h:90
gu_EdgeRingCost(const GU_PathSHedge &sh, GU_PathHedge::Interface *dhip)
SYS_FORCE_INLINE void zero()
PathEdge(GU_PathSHedge sh, GU_PathSHedge prev, const T &cost)
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
SYS_FORCE_INLINE T & getBestCost(const GU_PathSHedge &sh)
SYS_FORCE_INLINE bool isSet()
GU_PathSHedge getSHedge()
SYS_FORCE_INLINE bool isValid() const
Definition: GU_PathHedge.h:374
bool isEndOnBoundary()
gu_ShortestPathCost(const GU_PathSHedge &sh, GU_PathHedge::Interface *dhip)
GA_Size GA_Offset
Definition: GA_Types.h:641
GU_PathFinder< gu_EdgeRingCost > GU_EdgeRingFinder
gu_EdgeLoopCost(const gu_EdgeLoopCost &c)
GU_PathFinder< gu_EdgeLoopCost > GU_EdgeLoopFinder
GLboolean reset
Definition: glad.h:5138
gu_ShortestPathCost(fpreal l)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE fpreal getLength()
SYS_FORCE_INLINE bool isSet()
void resetAvoidGroups()
SYS_FORCE_INLINE const gu_ShortestPathCost & operator+=(const gu_ShortestPathCost &c)
#define GU_API
Definition: GU_API.h:14
void avoidPrimitives(GA_PrimitiveGroup *grp)
gu_EdgeRingCost & operator=(const gu_EdgeRingCost &c)=default
GU_WalkEndReason
GA_GroupType classType() const
Definition: GA_Group.h:54
GLdouble t
Definition: glad.h:2397
SYS_FORCE_INLINE bool operator>(const gu_EdgeLoopCost &c) const
void avoidVertices(GA_VertexGroup *grp)
gu_EdgeLoopCost()=default
static SYS_FORCE_INLINE gu_ShortestPathCost turnCost(GU_PathHedge::Interface *dhip, const GU_PathSHedge &from_sh, const GU_PathSHedge &to_sh, const GU_EdgeSuccessor &exits)
bool isStartOnBoundary()
SYS_FORCE_INLINE void unset()
bool operator()(PathEdge &p1, PathEdge &p2) const
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
SYS_FORCE_INLINE bool operator>(const gu_EdgeRingCost &c) const
SYS_FORCE_INLINE bool isSet()
fpreal64 fpreal
Definition: SYS_Types.h:277
GU_PathSHedge getPrev()
gu_EdgeLoopCost(fpreal len, int bends)
SYS_FORCE_INLINE bool operator>(const gu_ShortestPathCost &c) const
static SYS_FORCE_INLINE gu_EdgeRingCost turnCost(GU_PathHedge::Interface *dhip, const GU_PathSHedge &from_sh, const GU_PathSHedge &to_sh, const GU_EdgeSuccessor &successors)
gu_EdgeRingCost()=default
SYS_FORCE_INLINE void zero()
gu_EdgeRingCost(fpreal len, int bends)
Container class for all geometry.
Definition: GA_Detail.h:96
gu_ShortestPathCost()=default
void avoidEdges(GA_EdgeGroup *grp)
const GEO_DetachedHedgeInterface HedgeInterface
Definition: GU_Decompose.h:54
void setCollisionGroup(const GA_Group *group, bool exclude, bool strong)
SYS_FORCE_INLINE void zero()
SYS_FORCE_INLINE GA_Offset v0() const
Definition: GU_PathHedge.h:53
SYS_FORCE_INLINE const gu_EdgeRingCost & operator+=(const gu_EdgeRingCost &c)
gu_EdgeLoopCost(const GU_PathSHedge &sh, GU_PathHedge::Interface *dhip)
static Mask typeMask(Type t)
Definition: GU_PathFinder.h:72
static SYS_FORCE_INLINE gu_EdgeLoopCost turnCost(GU_PathHedge::Interface *dhip, const GU_PathSHedge &from_sh, const GU_PathSHedge &to_sh, const GU_EdgeSuccessor &successors)
SYS_FORCE_INLINE GA_Offset dstPoint(T &iface, GEO_Hedge h)
Definition: GEO_Hedge.h:244
GU_PathSHedge & operator()(int i)
Definition: GU_PathFinder.h:68