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