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  : public std::iterator<std::bidirectional_iterator_tag, T>
126  {
127  public:
128  /// Copy constructor, allows constructing a const_iterator
129  /// from a regular iterator.
130  template<typename ET, typename EIT>
132  {
133  myCurrent = src.myCurrent;
134  myEnd = src.myEnd;
135  }
136 
137  /// Assignment operator
138  template<typename ET, typename EIT>
140  {
141  myCurrent = src.myCurrent;
142  myEnd = src.myEnd;
143  return *this;
144  }
145 
146  /// Compare this iterator with another and return \c true if they
147  /// both point to the same element.
148  bool operator==(const base_iterator &cmp) const
149  { return myCurrent == cmp.myCurrent; }
150 
151  /// Compare this iterator with another and return \c true if they
152  /// point to different elements.
153  bool operator!=(const base_iterator &cmp) const
154  { return myCurrent != cmp.myCurrent; }
155 
156  /// Pre-increment operator. Advances the iterator to the next
157  /// element in the list.
159  { ++myCurrent; return *this; }
160 
161  /// Pre-decrement operator. Moves the iterator to the previous
162  /// element in the list.
164  { --myCurrent; return *this; }
165 
166  bool atEnd() const
167  { return myCurrent == myEnd; }
168 
169  void advance()
170  {
171  ++myCurrent;
172  }
173 
174  T &operator*() const { return myCurrent->myEdge; }
175  T *operator->() const { return &myCurrent->myEdge; }
176  T &getEdge() { return myCurrent->myEdge; }
177  GA_Offset getPrimitive() { return myCurrent->myPrim; }
178 
179  private:
180  friend class GA_EdgeGroup;
181 
182  base_iterator(IT current, IT end)
183  : myCurrent(current), myEnd(end) {}
184 
185  IT myCurrent;
186  IT myEnd;
187  };
188 
189 public:
192 
193  /// Default constructor.
194  GA_EdgeGroup(const GA_Detail &gdp,
195  const char *name="");
196  ~GA_EdgeGroup() override;
197 
198  const GA_Detail &getDetail() const override { return myGdp; }
199 
200  /// Report memory usage
201  int64 getMemoryUsage(bool inclusive) const override;
202 
203  /// Returns an iterator pointing at the beginning of the list of edges
204  /// of this edge group.
206  {
207  // NOTE: We don't need to harden yet, because the only difference
208  // between iterator and const_iterator is that iterator
209  // can be passed to remove(it).
210  return iterator(myData->myEdgeList.begin(), myData->myEdgeList.end());
211  }
212 
213  /// Returns an iterator pointing at the beginning of the list of edges
214  /// of this edge group.
216  { return iterator(myData->myEdgeList.end(), myData->myEdgeList.end()); }
217 
219  { return const_iterator(myData->myEdgeList.begin(), myData->myEdgeList.end()); }
220 
222  { return const_iterator(myData->myEdgeList.end(), myData->myEdgeList.end()); }
223 
224  /// Count memory usage using a UT_MemoryCounter in order to count
225  /// shared memory correctly.
226  /// If inclusive is true, the size of this object is counted,
227  /// else only memory owned by this object is counted.
228  /// If this is pointed to by the calling object, inclusive should be true.
229  /// If this is contained in the calling object, inclusive should be false.
230  /// (Its memory was already counted in the size of the calling object.)
231  void countMemory(UT_MemoryCounter &counter, bool inclusive) const override;
232 
233  /// Search for an edge matching the input. If the edge was found, it
234  /// returns an iterator pointing at the edge in the list. Otherwise returns
235  /// the \c end iterator.
236  /// @{
237  const_iterator find(const GA_Edge &edge,
238  GA_Offset primoff = GA_INVALID_OFFSET) const;
239  const_iterator find(const GA_Edge &edge,
240  const GA_Primitive *prim) const;
241  /// @}
242 
243  /// Search for an edge matching the input. If the edge was found, it
244  /// returns an iterator pointing at the edge in the list. Otherwise returns
245  /// the \c end iterator.
246  /// @{
247  iterator find(const GA_Edge &edge,
248  GA_Offset primoff = GA_INVALID_OFFSET);
249  iterator find(const GA_Edge &edge,
250  const GA_Primitive *prim);
251  /// @}
252 
253  /// Returns \c true if an edge exists in this group, matching the input
254  /// data.
255  /// @{
256  bool contains(const GA_Edge &edge,
257  GA_Offset primoff = GA_INVALID_OFFSET) const;
258  bool contains(const GA_Edge &edge,
259  const GA_Primitive *prim) const;
260  /// @}
261 
262  /// Add an edge to this group. Returns \c true if the edge was added,
263  /// and \c false if the edge already existed.
264  /// @{
265  bool add(const GA_Edge &edge,
266  GA_Offset primoff = GA_INVALID_OFFSET);
267  bool add(GA_Offset p0, GA_Offset p1,
268  GA_Offset primoff = GA_INVALID_OFFSET);
269  bool add(const GA_Edge &edge,
270  const GA_Primitive *prim);
271  bool add(GA_Offset p0, GA_Offset p1,
272  const GA_Primitive *prim);
273  /// @}
274 
275  /// Toggle the existence of all edges of the detail for this group.
276  void toggle();
277  void toggleEntries() { toggle(); }
278 
279  /// Toggles the existence of a given edge in the group. If the edge got
280  /// removed, then this function returns \c false, if it got added, however,
281  /// \c true is returned.
282  /// @{
283  bool toggle(const GA_Edge &edge,
284  GA_Offset primoff = GA_INVALID_OFFSET);
285  bool toggle(const GA_Edge &edge,
286  const GA_Primitive *prim);
287  /// @}
288 
289  /// Remove the edge pointed to by the iterator, and return an iterator
290  /// pointing to the next edge in the group.
291  iterator remove(iterator it);
292 
293  /// Remove the entry corresponding with the given edge and the optional
294  /// primitive. Returns \c true if an edge was deleted based on the
295  /// search data.
296  /// @{
297  bool remove(const GA_Edge &edge,
298  GA_Offset primoff = GA_INVALID_OFFSET);
299  bool remove(const GA_Edge &edge,
300  const GA_Primitive *prim);
301  /// @}
302 
303  /// Returns the number of edges in this group.
304  GA_Size entries() const override {return myData->myEdgeList.size();}
305 
306  /// Returns \c true if this edge group is empty.
307  bool isEmpty() const { return myData->myEdgeList.empty(); }
308 
309  /// Remove all edges from this group.
310  void clear() override;
311 
312  /// Add all edges from the associated detail into this edge group.
313  void addAll() override;
314 
315  /// Returns a boolean indicating whether this group is ordered or not.
316  /// Edge groups are always ordered.
317  bool isOrdered() const override;
318 
319  /// Returns a boolean indicating whether this group is mixed. Edge groups
320  /// are never mixed, so this function always returns \c false.
321  bool isMixed() const override;
322 
324  { return myData->myPrimEntryCount; }
325 
326  /// Combine another group with this edge group. Currently, only edge groups
327  /// are supported. Returns \c true if the other group was combined with
328  /// this one.
329  bool combine(const GA_Group * inputGroup) override;
330 
331  /// Save data to a JSON stream.
332  /// @section JSON-GA_EdgeGroup JSON Schema: GA_EdgeGroup
333  /// Private data for an edge group
334  /// @code
335  /// "name" : "GA_EdgeGroup",
336  /// "description" : "Private data for edge groups",
337  /// "type" : "orderedmap",
338  /// "properties": {
339  /// "points": {
340  /// "type" : "array",
341  /// "items" : "integer",
342  /// "description" :
343  /// "Flat array of points, 2 points per edge. The points
344  /// are stored in interleaved pairs representing the
345  /// start/end points of each edge.",
346  /// }
347  /// "primitives": {
348  /// "type" : "array",
349  /// "items" : "integer",
350  /// "description" : "Primitives tied to the edge. May be -1.",
351  /// "optional" : true,
352  /// }
353  /// },
354  /// @endcode
355  ///
356  /// @see @ref JSON_FileFormat, GA_GroupTable
358  const GA_SaveMap &m) const override;
359  /// Load the private JSON data
361  const GA_LoadMap &m) override;
362 
363  /// Combinatorial operatos.
364  GA_EdgeGroup &operator|=(const GA_EdgeGroup &inputGroup);
365  GA_EdgeGroup &operator&=(const GA_EdgeGroup &inputGroup);
366  GA_EdgeGroup &operator-=(const GA_EdgeGroup &inputGroup);
367  GA_EdgeGroup &operator+=(const GA_EdgeGroup &inputGroup);
368  GA_EdgeGroup &operator^=(const GA_EdgeGroup &inputGroup);
369  GA_EdgeGroup &operator =(const GA_EdgeGroup &inputGroup);
370 
372  {
373  return myData->myDataID;
374  }
375  void bumpDataId();
376  void cloneDataId(const GA_EdgeGroup &src);
377 
378  /// NOTE: You don't need to call this for groups in a SOP's output detail,
379  /// because it will call GA_EdgeGroupTable::makeAllEdgesValid(),
380  /// which can be more efficient than calling this for each edge
381  /// group, (if there are multiple).
382  /// This also won't do anything if the max of the topology data ID
383  /// and the primitive list data ID is equal to myLastValidTopoId,
384  /// so you have to make sure that any necessary bumping has occurred.
385  /// This was added for use by GU_EdgeSelection::validateEdges().
386  void makeAllEdgesValid();
387 
389  {
390  return myData->myLastValidTopoId;
391  }
392  void setValidTopoId(GA_DataId topology_data_id)
393  {
394  harden()->myLastValidTopoId = topology_data_id;
395  }
396 
398  {
399  return myData->myLastValidPrimListId;
400  }
401  void setValidPrimListId(GA_DataId primlist_data_id)
402  {
403  harden()->myLastValidPrimListId = primlist_data_id;
404  }
405 
406  /// Interface for defragmentation
407  void defragment(const GA_Defragment &defrag);
408 
409 private:
410  bool addEntry(const PrimEdge &edge);
411  void addEntryNoDuplicateCheck(const PrimEdge &edge);
412 
413  struct SharedData : public UT_IntrusiveRefCounter<SharedData>
414  {
415  SharedData();
416  SharedData(const SharedData &that)
417  : UT_IntrusiveRefCounter(that) // doesn't copy ref counter
418  , myEdgeList(that.myEdgeList)
419  , myEdgeMap(that.myEdgeMap)
420  , myPrimEntryCount(that.myPrimEntryCount)
421  , myDataID(that.myDataID)
422  , myLastValidTopoId(that.myLastValidTopoId)
423  , myLastValidPrimListId(that.myLastValidPrimListId)
424  {
425  // The map maps to iterators in the list, so we have to update them.
426  for (auto it = myEdgeList.begin(); it != myEdgeList.end(); ++it)
427  {
428  myEdgeMap[*it] = it;
429  }
430  }
431 
432  EdgeList myEdgeList;
433  EdgeMap myEdgeMap;
434  GA_Size myPrimEntryCount;
435  GA_DataId myDataID;
436 
437  /// This is the last topology data ID for which
438  /// this edge group was validated, or -1 if it has never been validated.
439  /// If getTopology().getDataId() returns something *not equal* to this
440  /// (not just greater than), it should be re-validated.
441  GA_DataId myLastValidTopoId;
442 
443  /// This is the last primitive list data ID for which
444  /// this edge group was validated, or -1 if it has never been validated.
445  /// If getPrimitiveList().getDataId() returns something *not equal* to this
446  /// (not just greater than), it should be re-validated.
447  GA_DataId myLastValidPrimListId;
448  };
449 
450  SharedData *harden()
451  {
452  if (myData->use_count() > 1)
453  myData.reset(new SharedData(*myData));
454  return myData.get();
455  }
456 
457  const GA_Detail &myGdp;
459 };
460 
462 
464 
465 #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:304
GA_DataId getDataId() const
Definition: GA_EdgeGroup.h:371
void toggleEntries()
Definition: GA_EdgeGroup.h:277
size_t operator()(const PrimEdge &key) const
Definition: GA_EdgeGroup.h:83
GLuint counter
Definition: glew.h:2745
bool operator==(const PrimEdge &o) const
Definition: GA_EdgeGroup.h:67
GA_DataId getLastValidPrimListId() const
Definition: GA_EdgeGroup.h:397
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
int64 GA_DataId
Definition: GA_Types.h:686
static SYS_FORCE_INLINE void clearConstruct(PairType *p)
Definition: GA_EdgeGroup.h:109
bool operator!=(const base_iterator &cmp) const
Definition: GA_EdgeGroup.h:153
bool GAisValid(GA_Size v)
Definition: GA_Types.h:648
base_iterator(const base_iterator< ET, EIT > &src)
Definition: GA_EdgeGroup.h:131
GA_DataId getLastValidTopoId() const
Definition: GA_EdgeGroup.h:388
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:88
#define GA_API
Definition: GA_API.h:14
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:35
GLuint const GLchar * name
Definition: glcorearb.h:786
virtual bool combine(const GA_Group *inputGroup)
GA_EdgeT< GA_Offset, false > GA_Edge
Definition: GA_Edge.h:91
GLenum src
Definition: glcorearb.h:1793
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.
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:234
virtual bool isMixed() const =0
virtual void clear()=0
#define GA_INVALID_OFFSET
Definition: GA_Types.h:677
base_iterator< const GA_Edge, EdgeList::const_iterator > const_iterator
Definition: GA_EdgeGroup.h:191
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
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
GA_Size GA_Offset
Definition: GA_Types.h:640
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
GA_EdgeGroup & operator=(const GA_EdgeGroup &inputGroup)
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:139
bool operator==(const base_iterator &cmp) const
Definition: GA_EdgeGroup.h:148
UT_UniquePtr< const GA_EdgeGroup > GA_ConstEdgeGroupUPtr
Definition: GA_EdgeGroup.h:463
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4369
void cloneDataId(const GA_EdgeGroup &src)
const GLdouble * v
Definition: glcorearb.h:837
GA_Size entriesWithPrimitive() const
Definition: GA_EdgeGroup.h:323
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
GLfloat GLfloat p
Definition: glew.h:16656
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:33
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
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
const_iterator begin() const
Definition: GA_EdgeGroup.h:218
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:198
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:307
iterator end()
Definition: GA_EdgeGroup.h:215
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:392
const GLdouble * m
Definition: glew.h:9166
iterator begin()
Definition: GA_EdgeGroup.h:205
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4392
Container class for all geometry.
Definition: GA_Detail.h:95
base_iterator & operator--()
Definition: GA_EdgeGroup.h:163
T p0() const
Definition: GA_Edge.h:31
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:221
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:190
base_iterator & operator++()
Definition: GA_EdgeGroup.h:158
void setValidPrimListId(GA_DataId primlist_data_id)
Definition: GA_EdgeGroup.h:401
UT_UniquePtr< GA_EdgeGroup > GA_EdgeGroupUPtr
Definition: GA_EdgeGroup.h:461
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