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