HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_EdgeGroup.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: GA_EdgeGroup.h (GA Library, C++)
7  *
8  * COMMENTS: GA_EdgeGroup is a group container for GA_Edge entities
9  * and optional primitive references.
10  */
11 
12 #pragma once
13 
14 #ifndef __GA_EdgeGroup_h__
15 #define __GA_EdgeGroup_h__
16 
17 #include "GA_API.h"
18 
19 #include "GA_Edge.h"
20 #include "GA_Group.h"
21 #include "GA_Types.h"
22 
23 #include <UT/UT_IntrusivePtr.h>
24 #include <UT/UT_ArrayMap.h>
25 #include "UT/UT_UniquePtr.h"
26 #include <SYS/SYS_Hash.h>
27 #include <SYS/SYS_Types.h>
28 
29 #include <list>
30 #include <iterator>
31 
32 class GA_Defragment;
33 class GA_Detail;
34 class GA_Primitive;
35 class GA_LoadMap;
36 class GA_SaveMap;
37 class UT_JSONParser;
38 class UT_JSONWriter;
39 class UT_MemoryCounter;
40 
41 
43 {
44 private:
45  // Only GA_EdgeGroupTable can make non-detached edge groups.
46  friend class GA_EdgeGroupTable;
47 
48  GA_EdgeGroup(const GA_Detail &gdp,
49  const UT_StringHolder &name,
50  bool internal,
51  bool detached);
52 public:
53  class PrimEdge;
54 private:
55  using EdgeList = std::list<PrimEdge>;
56 public:
57  /// The edge data we store internally
58  class PrimEdge
59  {
60  public:
61  PrimEdge() {}
63  : myEdge(e)
64  , myPrim(prim)
65  {}
66 
67  bool operator==(const PrimEdge &o) const
68  { return myEdge == o.myEdge && myPrim == o.myPrim; }
69 
70  bool operator!=(const PrimEdge &o) const
71  { return myEdge != o.myEdge || myPrim != o.myPrim; }
72 
74  {
75  SYS_HashType hash = myEdge.hash();
76 
77  SYShashCombine(hash, myPrim);
78  return hash;
79  }
80 
81  struct Hasher
82  {
83  size_t operator()(const PrimEdge &key) const { return key.hash(); }
84  };
85  struct Clearer
86  {
87  using PairType = std::pair<PrimEdge,EdgeList::iterator>;
89  {
90  clear(v.first);
91  v.second = EdgeList::iterator();
92  }
94  {
97  }
98  /// Only need to actually check the key,
99  /// even though clear and clearConstruct will clear both.
100  static SYS_FORCE_INLINE bool isClear(const PairType &v)
101  {
102  return isClear(v.first);
103  }
104  /// An overload for when there's only a key.
105  static SYS_FORCE_INLINE bool isClear(const PrimEdge &v)
106  {
107  return !GAisValid(v.myEdge.p0()) && !GAisValid(v.myEdge.p1()) && !GAisValid(v.myPrim);
108  }
109  static SYS_FORCE_INLINE void clearConstruct(PairType *p) { clear(*p); }
110  static SYS_FORCE_INLINE void clearConstruct(PrimEdge *p) { clear(*p); }
111 
112  static const bool clearNeedsDestruction = false;
113  };
114 
117  };
118 
119 private:
121 
122 protected:
123  template<typename T, typename IT>
125  {
126  public:
127  using iterator_category = std::bidirectional_iterator_tag;
128  using value_type = T;
129  using difference_type = std::ptrdiff_t;
130  using pointer = T*;
131  using reference = T&;
132 
133  /// Copy constructor, allows constructing a const_iterator
134  /// from a regular iterator.
135  template<typename ET, typename EIT>
137  {
138  myCurrent = src.myCurrent;
139  myEnd = src.myEnd;
140  }
141 
142  /// Assignment operator
143  template<typename ET, typename EIT>
145  {
146  myCurrent = src.myCurrent;
147  myEnd = src.myEnd;
148  return *this;
149  }
150 
151  /// Compare this iterator with another and return \c true if they
152  /// both point to the same element.
153  bool operator==(const base_iterator &cmp) const
154  { return myCurrent == cmp.myCurrent; }
155 
156  /// Compare this iterator with another and return \c true if they
157  /// point to different elements.
158  bool operator!=(const base_iterator &cmp) const
159  { return myCurrent != cmp.myCurrent; }
160 
161  /// Pre-increment operator. Advances the iterator to the next
162  /// element in the list.
164  { ++myCurrent; return *this; }
165 
166  /// Pre-decrement operator. Moves the iterator to the previous
167  /// element in the list.
169  { --myCurrent; return *this; }
170 
171  bool atEnd() const
172  { return myCurrent == myEnd; }
173 
174  void advance()
175  {
176  ++myCurrent;
177  }
178 
179  T &operator*() const { return myCurrent->myEdge; }
180  T *operator->() const { return &myCurrent->myEdge; }
181  T &getEdge() { return myCurrent->myEdge; }
182  GA_Offset getPrimitive() { return myCurrent->myPrim; }
183 
184  private:
185  friend class GA_EdgeGroup;
186 
187  base_iterator(IT current, IT end)
188  : myCurrent(current), myEnd(end) {}
189 
190  IT myCurrent;
191  IT myEnd;
192  };
193 
194 public:
197 
198  /// Default constructor.
199  GA_EdgeGroup(const GA_Detail &gdp,
200  const char *name="");
201  ~GA_EdgeGroup() override;
202 
203  const GA_Detail &getDetail() const override { return myGdp; }
204 
205  /// Report memory usage
206  int64 getMemoryUsage(bool inclusive) const override;
207 
208  /// Returns an iterator pointing at the beginning of the list of edges
209  /// of this edge group.
211  {
212  // NOTE: We don't need to harden yet, because the only difference
213  // between iterator and const_iterator is that iterator
214  // can be passed to remove(it).
215  return iterator(myData->myEdgeList.begin(), myData->myEdgeList.end());
216  }
217 
218  /// Returns an iterator pointing at the beginning of the list of edges
219  /// of this edge group.
221  { return iterator(myData->myEdgeList.end(), myData->myEdgeList.end()); }
222 
224  { return const_iterator(myData->myEdgeList.begin(), myData->myEdgeList.end()); }
225 
227  { return const_iterator(myData->myEdgeList.end(), myData->myEdgeList.end()); }
228 
229  /// Count memory usage using a UT_MemoryCounter in order to count
230  /// shared memory correctly.
231  /// If inclusive is true, the size of this object is counted,
232  /// else only memory owned by this object is counted.
233  /// If this is pointed to by the calling object, inclusive should be true.
234  /// If this is contained in the calling object, inclusive should be false.
235  /// (Its memory was already counted in the size of the calling object.)
236  void countMemory(UT_MemoryCounter &counter, bool inclusive) const override;
237 
238  /// Search for an edge matching the input. If the edge was found, it
239  /// returns an iterator pointing at the edge in the list. Otherwise returns
240  /// the \c end iterator.
241  /// @{
242  const_iterator find(const GA_Edge &edge,
243  GA_Offset primoff = GA_INVALID_OFFSET) const;
244  const_iterator find(const GA_Edge &edge,
245  const GA_Primitive *prim) const;
246  /// @}
247 
248  /// Search for an edge matching the input. If the edge was found, it
249  /// returns an iterator pointing at the edge in the list. Otherwise returns
250  /// the \c end iterator.
251  /// @{
252  iterator find(const GA_Edge &edge,
253  GA_Offset primoff = GA_INVALID_OFFSET);
254  iterator find(const GA_Edge &edge,
255  const GA_Primitive *prim);
256  /// @}
257 
258  /// Returns \c true if an edge exists in this group, matching the input
259  /// data.
260  /// @{
261  bool contains(const GA_Edge &edge,
262  GA_Offset primoff = GA_INVALID_OFFSET) const;
263  bool contains(const GA_Edge &edge,
264  const GA_Primitive *prim) const;
265  /// @}
266 
267  /// Add an edge to this group. Returns \c true if the edge was added,
268  /// and \c false if the edge already existed.
269  /// @{
270  bool add(const GA_Edge &edge,
271  GA_Offset primoff = GA_INVALID_OFFSET);
272  bool add(GA_Offset p0, GA_Offset p1,
273  GA_Offset primoff = GA_INVALID_OFFSET);
274  bool add(const GA_Edge &edge,
275  const GA_Primitive *prim);
276  bool add(GA_Offset p0, GA_Offset p1,
277  const GA_Primitive *prim);
278  /// @}
279 
280  /// Toggle the existence of all edges of the detail for this group.
281  void toggle();
282  void toggleEntries() { toggle(); }
283 
284  /// Toggles the existence of a given edge in the group. If the edge got
285  /// removed, then this function returns \c false, if it got added, however,
286  /// \c true is returned.
287  /// @{
288  bool toggle(const GA_Edge &edge,
289  GA_Offset primoff = GA_INVALID_OFFSET);
290  bool toggle(const GA_Edge &edge,
291  const GA_Primitive *prim);
292  /// @}
293 
294  /// Remove the edge pointed to by the iterator, and return an iterator
295  /// pointing to the next edge in the group.
296  iterator remove(iterator it);
297 
298  /// Remove the entry corresponding with the given edge and the optional
299  /// primitive. Returns \c true if an edge was deleted based on the
300  /// search data.
301  /// @{
302  bool remove(const GA_Edge &edge,
303  GA_Offset primoff = GA_INVALID_OFFSET);
304  bool remove(const GA_Edge &edge,
305  const GA_Primitive *prim);
306  /// @}
307 
308  /// Returns the number of edges in this group.
309  GA_Size entries() const override {return myData->myEdgeList.size();}
310 
311  /// Returns \c true if this edge group is empty.
312  bool isEmpty() const { return myData->myEdgeList.empty(); }
313 
314  /// Remove all edges from this group.
315  void clear() override;
316 
317  /// Add all edges from the associated detail into this edge group.
318  void addAll() override;
319 
320  /// Returns a boolean indicating whether this group is ordered or not.
321  /// Edge groups are always ordered.
322  bool isOrdered() const override;
323 
324  /// Returns a boolean indicating whether this group is mixed. Edge groups
325  /// are never mixed, so this function always returns \c false.
326  bool isMixed() const override;
327 
329  { return myData->myPrimEntryCount; }
330 
331  /// Combine another group with this edge group. Currently, only edge groups
332  /// are supported. Returns \c true if the other group was combined with
333  /// this one.
334  bool combine(const GA_Group *input_group) override;
335 
336  /// Save data to a JSON stream.
337  /// @section JSON-GA_EdgeGroup JSON Schema: GA_EdgeGroup
338  /// Private data for an edge group
339  /// @code
340  /// "name" : "GA_EdgeGroup",
341  /// "description" : "Private data for edge groups",
342  /// "type" : "orderedmap",
343  /// "properties": {
344  /// "points": {
345  /// "type" : "array",
346  /// "items" : "integer",
347  /// "description" :
348  /// "Flat array of points, 2 points per edge. The points
349  /// are stored in interleaved pairs representing the
350  /// start/end points of each edge.",
351  /// }
352  /// "primitives": {
353  /// "type" : "array",
354  /// "items" : "integer",
355  /// "description" : "Primitives tied to the edge. May be -1.",
356  /// "optional" : true,
357  /// }
358  /// },
359  /// @endcode
360  ///
361  /// @see @ref JSON_FileFormat, GA_GroupTable
363  const GA_SaveMap &m) const override;
364  /// Load the private JSON data
366  const GA_LoadMap &m) override;
367 
368  /// Combinatorial operatos.
369  GA_EdgeGroup &operator|=(const GA_EdgeGroup &input_group);
370  GA_EdgeGroup &operator&=(const GA_EdgeGroup &input_group);
371  GA_EdgeGroup &operator-=(const GA_EdgeGroup &input_group);
372  GA_EdgeGroup &operator+=(const GA_EdgeGroup &input_group);
373  GA_EdgeGroup &operator^=(const GA_EdgeGroup &input_group);
374  GA_EdgeGroup &operator =(const GA_EdgeGroup &input_group);
375 
377  {
378  return myData->myDataID;
379  }
380  void bumpDataId();
381  void cloneDataId(const GA_EdgeGroup &src);
382 
383  /// NOTE: You don't need to call this for groups in a SOP's output detail,
384  /// because it will call GA_EdgeGroupTable::makeAllEdgesValid(),
385  /// which can be more efficient than calling this for each edge
386  /// group, (if there are multiple).
387  /// This also won't do anything if the max of the topology data ID
388  /// and the primitive list data ID is equal to myLastValidTopoId,
389  /// so you have to make sure that any necessary bumping has occurred.
390  /// This was added for use by GU_EdgeSelection::validateEdges().
391  void makeAllEdgesValid();
392 
394  {
395  return myData->myLastValidTopoId;
396  }
397  void setValidTopoId(GA_DataId topology_data_id)
398  {
399  harden()->myLastValidTopoId = topology_data_id;
400  }
401 
403  {
404  return myData->myLastValidPrimListId;
405  }
406  void setValidPrimListId(GA_DataId primlist_data_id)
407  {
408  harden()->myLastValidPrimListId = primlist_data_id;
409  }
410 
411  /// Interface for defragmentation
412  void defragment(const GA_Defragment &defrag);
413 
414 private:
415  bool addEntry(const PrimEdge &edge);
416  void addEntryNoDuplicateCheck(const PrimEdge &edge);
417 
418  struct SharedData : public UT_IntrusiveRefCounter<SharedData>
419  {
420  SharedData();
421  SharedData(const SharedData &that)
422  : UT_IntrusiveRefCounter(that) // doesn't copy ref counter
423  , myEdgeList(that.myEdgeList)
424  , myEdgeMap(that.myEdgeMap)
425  , myPrimEntryCount(that.myPrimEntryCount)
426  , myDataID(that.myDataID)
427  , myLastValidTopoId(that.myLastValidTopoId)
428  , myLastValidPrimListId(that.myLastValidPrimListId)
429  {
430  // The map maps to iterators in the list, so we have to update them.
431  for (auto it = myEdgeList.begin(); it != myEdgeList.end(); ++it)
432  {
433  myEdgeMap[*it] = it;
434  }
435  }
436 
437  EdgeList myEdgeList;
438  EdgeMap myEdgeMap;
439  GA_Size myPrimEntryCount;
440  GA_DataId myDataID;
441 
442  /// This is the last topology data ID for which
443  /// this edge group was validated, or -1 if it has never been validated.
444  /// If getTopology().getDataId() returns something *not equal* to this
445  /// (not just greater than), it should be re-validated.
446  GA_DataId myLastValidTopoId;
447 
448  /// This is the last primitive list data ID for which
449  /// this edge group was validated, or -1 if it has never been validated.
450  /// If getPrimitiveList().getDataId() returns something *not equal* to this
451  /// (not just greater than), it should be re-validated.
452  GA_DataId myLastValidPrimListId;
453  };
454 
455  SharedData *harden()
456  {
457  if (myData->use_count() > 1)
458  myData.reset(new SharedData(*myData));
459  return myData.get();
460  }
461 
462  const GA_Detail &myGdp;
464 };
465 
467 
469 
470 #endif
virtual int64 getMemoryUsage(bool inclusive) const =0
GA_Size entries() const override
Returns the number of edges in this group.
Definition: GA_EdgeGroup.h:309
GA_DataId getDataId() const
Definition: GA_EdgeGroup.h:376
void toggleEntries()
Definition: GA_EdgeGroup.h:282
size_t operator()(const PrimEdge &key) const
Definition: GA_EdgeGroup.h:83
bool operator==(const PrimEdge &o) const
Definition: GA_EdgeGroup.h:67
GA_DataId getLastValidPrimListId() const
Definition: GA_EdgeGroup.h:402
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
int64 GA_DataId
Definition: GA_Types.h:687
const GLdouble * v
Definition: glcorearb.h:837
static SYS_FORCE_INLINE void clearConstruct(PairType *p)
Definition: GA_EdgeGroup.h:109
bool operator!=(const base_iterator &cmp) const
Definition: GA_EdgeGroup.h:158
bool GAisValid(GA_Size v)
Definition: GA_Types.h:649
base_iterator(const base_iterator< ET, EIT > &src)
Definition: GA_EdgeGroup.h:136
GA_DataId getLastValidTopoId() const
Definition: GA_EdgeGroup.h:393
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define GA_API
Definition: GA_API.h:14
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
GA_EdgeT< GA_Offset, false > GA_Edge
Definition: GA_Edge.h:90
std::enable_if< UT_EnableBitMask< T >::enable, T & >::type operator&=(T &lhs, T rhs)
Definition: UT_EnumHelper.h:57
A reference counter base class for use with UT_IntrusivePtr.
GA_EdgeGroup & operator=(const GA_EdgeGroup &input_group)
static SYS_FORCE_INLINE void clearConstruct(PrimEdge *p)
Definition: GA_EdgeGroup.h:110
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:235
virtual bool isMixed() const =0
virtual void clear()=0
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
base_iterator< const GA_Edge, EdgeList::const_iterator > const_iterator
Definition: GA_EdgeGroup.h:196
virtual void countMemory(UT_MemoryCounter &counter, bool inclusive) const =0
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
IMATH_HOSTDEVICE constexpr int cmp(T a, T b) IMATH_NOEXCEPT
Definition: ImathFun.h:84
~GA_EdgeGroup() override
GA_Size GA_Offset
Definition: GA_Types.h:641
void makeAllEdgesValid()
virtual bool isOrdered() const =0
auto base_iterator(std::back_insert_iterator< Container > &it, checked_ptr< typename Container::value_type >) -> std::back_insert_iterator< Container >
Definition: format.h:394
virtual bool jsonSaveData(UT_JSONWriter &w, const GA_SaveMap &map) const =0
Save the private group data.
const base_iterator & operator=(const base_iterator< ET, EIT > &src)
Assignment operator.
Definition: GA_EdgeGroup.h:144
bool operator==(const base_iterator &cmp) const
Definition: GA_EdgeGroup.h:153
UT_UniquePtr< const GA_EdgeGroup > GA_ConstEdgeGroupUPtr
Definition: GA_EdgeGroup.h:468
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4369
void cloneDataId(const GA_EdgeGroup &src)
GA_Size entriesWithPrimitive() const
Definition: GA_EdgeGroup.h:328
GLuint GLuint end
Definition: glcorearb.h:475
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
bool operator!=(const PrimEdge &o) const
Definition: GA_EdgeGroup.h:70
SYS_HashType hash() const
Definition: GA_EdgeGroup.h:73
virtual void addAll()=0
long long int64
Definition: SYS_Types.h:116
The edge data we store internally.
Definition: GA_EdgeGroup.h:58
Options during loading.
Definition: GA_LoadMap.h:42
T p1() const
Definition: GA_Edge.h:32
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
GLuint const GLchar * name
Definition: glcorearb.h:786
static SYS_FORCE_INLINE void clear(PairType &v)
Definition: GA_EdgeGroup.h:88
void toggle()
Toggle the existence of all edges of the detail for this group.
void defragment(const GA_Defragment &defrag)
Interface for defragmentation.
static SYS_FORCE_INLINE bool isClear(const PairType &v)
Definition: GA_EdgeGroup.h:100
virtual bool combine(const GA_Group *input_group)
const_iterator begin() const
Definition: GA_EdgeGroup.h:223
static SYS_FORCE_INLINE void clear(PrimEdge &v)
Definition: GA_EdgeGroup.h:93
static SYS_FORCE_INLINE bool isClear(const PrimEdge &v)
An overload for when there's only a key.
Definition: GA_EdgeGroup.h:105
const GA_Detail & getDetail() const override
Definition: GA_EdgeGroup.h:203
virtual bool jsonLoadData(UT_JSONParser &p, const GA_LoadMap &map)=0
Load the private group data.
PrimEdge(const GA_Edge &e, GA_Offset prim=GA_INVALID_OFFSET)
Definition: GA_EdgeGroup.h:62
std::pair< PrimEdge, EdgeList::iterator > PairType
Definition: GA_EdgeGroup.h:87
bool isEmpty() const
Returns true if this edge group is empty.
Definition: GA_EdgeGroup.h:312
std::ptrdiff_t difference_type
Definition: GA_EdgeGroup.h:129
iterator end()
Definition: GA_EdgeGroup.h:220
std::enable_if< UT_EnableBitMask< T >::enable, T & >::type operator^=(T &lhs, T rhs)
Definition: UT_EnumHelper.h:76
void setValidTopoId(GA_DataId topology_data_id)
Definition: GA_EdgeGroup.h:397
iterator begin()
Definition: GA_EdgeGroup.h:210
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4392
Container class for all geometry.
Definition: GA_Detail.h:96
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
base_iterator & operator--()
Definition: GA_EdgeGroup.h:168
T p0() const
Definition: GA_Edge.h:30
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const_iterator end() const
Definition: GA_EdgeGroup.h:226
bool OIIO_UTIL_API contains(string_view a, string_view b)
Does 'a' contain the string 'b' within it?
base_iterator< const GA_Edge, EdgeList::iterator > iterator
Definition: GA_EdgeGroup.h:195
base_iterator & operator++()
Definition: GA_EdgeGroup.h:163
void setValidPrimListId(GA_DataId primlist_data_id)
Definition: GA_EdgeGroup.h:406
UT_UniquePtr< GA_EdgeGroup > GA_EdgeGroupUPtr
Definition: GA_EdgeGroup.h:466
std::bidirectional_iterator_tag iterator_category
Definition: GA_EdgeGroup.h:127
void bumpDataId()
std::enable_if< UT_EnableBitMask< T >::enable, T & >::type operator|=(T &lhs, T rhs)
Definition: UT_EnumHelper.h:37
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
GLenum src
Definition: glcorearb.h:1793