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