Developer Documentation
PropertyContainer.hh
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 
44 #ifndef OPENMESH_PROPERTYCONTAINER
45 #define OPENMESH_PROPERTYCONTAINER
46 
47 // Use static casts when not debugging
48 #ifdef NDEBUG
49 #define OM_FORCE_STATIC_CAST
50 #endif
51 
52 #include <OpenMesh/Core/Utils/Property.hh>
53 
54 //-----------------------------------------------------------------------------
55 namespace OpenMesh
56 {
57 //== FORWARDDECLARATIONS ======================================================
58  class BaseKernel;
59 
60 //== CLASS DEFINITION =========================================================
63 {
64 public:
65 
66  //-------------------------------------------------- constructor / destructor
67 
69  virtual ~PropertyContainer() { std::for_each(properties_.begin(), properties_.end(), Delete()); }
70 
71 
72  //------------------------------------------------------------- info / access
73 
74  typedef std::vector<BaseProperty*> Properties;
75  const Properties& properties() const { return properties_; }
76  size_t size() const { return properties_.size(); }
77 
78 
79 
80  //--------------------------------------------------------- copy / assignment
81 
82  PropertyContainer(const PropertyContainer& _rhs) { operator=(_rhs); }
83 
84  PropertyContainer& operator=(const PropertyContainer& _rhs)
85  {
86  // The assignment below relies on all previous BaseProperty* elements having been deleted
87  std::for_each(properties_.begin(), properties_.end(), Delete());
88  properties_ = _rhs.properties_;
89  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
90  for (; p_it!=p_end; ++p_it)
91  if (*p_it)
92  *p_it = (*p_it)->clone();
93  return *this;
94  }
95 
96 
97 
98  //--------------------------------------------------------- manage properties
99 
100  template <class T>
101  BasePropHandleT<T> add(const T&, const std::string& _name="<unknown>")
102  {
103  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
104  int idx=0;
105  for ( ; p_it!=p_end && *p_it!=NULL; ++p_it, ++idx ) {};
106  if (p_it==p_end) properties_.push_back(NULL);
107  properties_[idx] = new PropertyT<T>(_name);
108  return BasePropHandleT<T>(idx);
109  }
110 
111 
112  template <class T>
113  BasePropHandleT<T> handle(const T&, const std::string& _name) const
114  {
115  Properties::const_iterator p_it = properties_.begin();
116  for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
117  {
118  if (*p_it != NULL &&
119  (*p_it)->name() == _name //skip deleted properties
120 // Skip type check
121 #ifndef OM_FORCE_STATIC_CAST
122  && dynamic_cast<PropertyT<T>*>(properties_[idx]) != NULL //check type
123 #endif
124  )
125  {
126  return BasePropHandleT<T>(idx);
127  }
128  }
129  return BasePropHandleT<T>();
130  }
131 
132  BaseProperty* property( const std::string& _name ) const
133  {
134  Properties::const_iterator p_it = properties_.begin();
135  for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
136  {
137  if (*p_it != NULL && (*p_it)->name() == _name) //skip deleted properties
138  {
139  return *p_it;
140  }
141  }
142  return NULL;
143  }
144 
145  template <class T> PropertyT<T>& property(BasePropHandleT<T> _h)
146  {
147  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
148  assert(properties_[_h.idx()] != NULL);
149 #ifdef OM_FORCE_STATIC_CAST
150  return *static_cast <PropertyT<T>*> (properties_[_h.idx()]);
151 #else
152  PropertyT<T>* p = dynamic_cast<PropertyT<T>*>(properties_[_h.idx()]);
153  assert(p != NULL);
154  return *p;
155 #endif
156  }
157 
158 
159  template <class T> const PropertyT<T>& property(BasePropHandleT<T> _h) const
160  {
161  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
162  assert(properties_[_h.idx()] != NULL);
163 #ifdef OM_FORCE_STATIC_CAST
164  return *static_cast<PropertyT<T>*>(properties_[_h.idx()]);
165 #else
166  PropertyT<T>* p = dynamic_cast<PropertyT<T>*>(properties_[_h.idx()]);
167  assert(p != NULL);
168  return *p;
169 #endif
170  }
171 
172 
173  template <class T> void remove(BasePropHandleT<T> _h)
174  {
175  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
176  delete properties_[_h.idx()];
177  properties_[_h.idx()] = NULL;
178  }
179 
180 
181  void clear()
182  {
183  // Clear properties vector:
184  // Replaced the old version with new one
185  // which performs a swap to clear values and
186  // deallocate memory.
187 
188  // Old version (changed 22.07.09) {
189  // std::for_each(properties_.begin(), properties_.end(), Delete());
190  // }
191 
192  std::for_each(properties_.begin(), properties_.end(), ClearAll());
193  }
194 
195 
196  //---------------------------------------------------- synchronize properties
197 
198 /*
199  * In C++11 an beyond we can introduce more efficient and more legible
200  * implementations of the following methods.
201  */
202 #if ((defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
203 
206  void reserve(size_t _n) const {
207  std::for_each(properties_.begin(), properties_.end(),
208  [_n](BaseProperty* p) { if (p) p->reserve(_n); });
209  }
210 
214  void resize(size_t _n) const {
215  std::for_each(properties_.begin(), properties_.end(),
216  [_n](BaseProperty* p) { if (p) p->resize(_n); });
217  }
218 
227  void resize_if_smaller(size_t _n) const {
228  std::for_each(properties_.begin(), properties_.end(),
229  [_n](BaseProperty* p) { if (p && p->n_elements() < _n) p->resize(_n); });
230  }
231 
236  void swap(size_t _i0, size_t _i1) const {
237  std::for_each(properties_.begin(), properties_.end(),
238  [_i0, _i1](BaseProperty* p) { if (p) p->swap(_i0, _i1); });
239  }
240 #else
241 
244  void reserve(size_t _n) const {
245  std::for_each(properties_.begin(), properties_.end(), Reserve(_n));
246  }
247 
251  void resize(size_t _n) const {
252  std::for_each(properties_.begin(), properties_.end(), Resize(_n));
253  }
254 
263  void resize_if_smaller(size_t _n) const {
264  std::for_each(properties_.begin(), properties_.end(), ResizeIfSmaller(_n));
265  }
266 
271  void swap(size_t _i0, size_t _i1) const {
272  std::for_each(properties_.begin(), properties_.end(), Swap(_i0, _i1));
273  }
274 #endif
275 
276 
277 
278 protected: // generic add/get
279 
280  size_t _add( BaseProperty* _bp )
281  {
282  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
283  size_t idx=0;
284  for (; p_it!=p_end && *p_it!=NULL; ++p_it, ++idx) {};
285  if (p_it==p_end) properties_.push_back(NULL);
286  properties_[idx] = _bp;
287  return idx;
288  }
289 
290  BaseProperty& _property( size_t _idx )
291  {
292  assert( _idx < properties_.size());
293  assert( properties_[_idx] != NULL);
294  BaseProperty *p = properties_[_idx];
295  assert( p != NULL );
296  return *p;
297  }
298 
299  const BaseProperty& _property( size_t _idx ) const
300  {
301  assert( _idx < properties_.size());
302  assert( properties_[_idx] != NULL);
303  BaseProperty *p = properties_[_idx];
304  assert( p != NULL );
305  return *p;
306  }
307 
308 
309  typedef Properties::iterator iterator;
310  typedef Properties::const_iterator const_iterator;
311  iterator begin() { return properties_.begin(); }
312  iterator end() { return properties_.end(); }
313  const_iterator begin() const { return properties_.begin(); }
314  const_iterator end() const { return properties_.end(); }
315 
316  friend class BaseKernel;
317 
318 private:
319 
320  //-------------------------------------------------- synchronization functors
321 
322 #ifndef DOXY_IGNORE_THIS
323  struct Reserve
324  {
325  Reserve(size_t _n) : n_(_n) {}
326  void operator()(BaseProperty* _p) const { if (_p) _p->reserve(n_); }
327  size_t n_;
328  };
329 
330  struct Resize
331  {
332  Resize(size_t _n) : n_(_n) {}
333  void operator()(BaseProperty* _p) const { if (_p) _p->resize(n_); }
334  size_t n_;
335  };
336 
337  struct ResizeIfSmaller
338  {
339  ResizeIfSmaller(size_t _n) : n_(_n) {}
340  void operator()(BaseProperty* _p) const { if (_p && _p->n_elements() < n_) _p->resize(n_); }
341  size_t n_;
342  };
343 
344  struct ClearAll
345  {
346  ClearAll() {}
347  void operator()(BaseProperty* _p) const { if (_p) _p->clear(); }
348  };
349 
350  struct Swap
351  {
352  Swap(size_t _i0, size_t _i1) : i0_(_i0), i1_(_i1) {}
353  void operator()(BaseProperty* _p) const { if (_p) _p->swap(i0_, i1_); }
354  size_t i0_, i1_;
355  };
356 
357  struct Delete
358  {
359  Delete() {}
360  void operator()(BaseProperty* _p) const { if (_p) delete _p; _p=NULL; }
361  };
362 #endif
363 
364  Properties properties_;
365 };
366 
367 }//namespace OpenMesh
368 
369 #endif//OPENMESH_PROPERTYCONTAINER
370 
void resize(size_t _n) const
A a container for properties.
virtual void resize(size_t _n)=0
Resize storage to hold n elements.
virtual size_t n_elements() const =0
Number of elements in property.
void swap(size_t _i0, size_t _i1) const
virtual void reserve(size_t _n)=0
Reserve memory for n elements.
virtual void swap(size_t _i0, size_t _i1)=0
Let two elements swap their storage place.
Base property handle.
Definition: Property.hh:466
Default property class for any type T.
Definition: Property.hh:89
int idx() const
Get the underlying index of this handle.
Definition: Handles.hh:69
void resize_if_smaller(size_t _n) const
void reserve(size_t _n) const
virtual void clear()=0
Clear all elements and free memory.