OpenMesh
PropertyContainer.hh
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2022, 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 #include <OpenMesh/Core/Utils/Property.hh>
48 #include <OpenMesh/Core/Utils/typename.hh>
49 
50 //-----------------------------------------------------------------------------
51 namespace OpenMesh
52 {
53 //== FORWARDDECLARATIONS ======================================================
54  class BaseKernel;
55 
56 //== CLASS DEFINITION =========================================================
59 {
60 public:
61 
62  //-------------------------------------------------- constructor / destructor
63 
65  virtual ~PropertyContainer() { std::for_each(properties_.begin(), properties_.end(), Delete()); }
66 
67 
68  //------------------------------------------------------------- info / access
69 
70  typedef std::vector<BaseProperty*> Properties;
71  const Properties& properties() const { return properties_; }
72  size_t size() const { return properties_.size(); }
73 
74 
75 
76  //--------------------------------------------------------- copy / assignment
77 
78  PropertyContainer(const PropertyContainer& _rhs) { operator=(_rhs); }
79 
80  PropertyContainer& operator=(const PropertyContainer& _rhs)
81  {
82  // The assignment below relies on all previous BaseProperty* elements having been deleted
83  std::for_each(properties_.begin(), properties_.end(), Delete());
84  properties_ = _rhs.properties_;
85  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
86  for (; p_it!=p_end; ++p_it)
87  if (*p_it)
88  *p_it = (*p_it)->clone();
89  return *this;
90  }
91 
92 
93 
94  //--------------------------------------------------------- manage properties
95 
96  template <class T>
97  BasePropHandleT<T> add(const T&, const std::string& _name="<unknown>")
98  {
99  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
100  int idx=0;
101  for ( ; p_it!=p_end && *p_it!=nullptr; ++p_it, ++idx ) {};
102  if (p_it==p_end) properties_.push_back(nullptr);
103  properties_[idx] = new PropertyT<T>(_name, get_type_name<T>() ); // create a new property with requested name and given (system dependent) internal typename
104  return BasePropHandleT<T>(idx);
105  }
106 
107 
108  template <class T>
109  BasePropHandleT<T> handle(const T&, const std::string& _name) const
110  {
111  Properties::const_iterator p_it = properties_.begin();
112  for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
113  {
114  if (*p_it != nullptr &&
115  (*p_it)->name() == _name //skip deleted properties
116  && (*p_it)->internal_type_name() == get_type_name<T>() // new check type
117  )
118  {
119  return BasePropHandleT<T>(idx);
120  }
121  }
122  return BasePropHandleT<T>();
123  }
124 
125  BaseProperty* property( const std::string& _name ) const
126  {
127  Properties::const_iterator p_it = properties_.begin();
128  for (int idx=0; p_it != properties_.end(); ++p_it, ++idx)
129  {
130  if (*p_it != nullptr && (*p_it)->name() == _name) //skip deleted properties
131  {
132  return *p_it;
133  }
134  }
135  return nullptr;
136  }
137 
138  template <class T> PropertyT<T>& property(BasePropHandleT<T> _h)
139  {
140  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
141  assert(properties_[_h.idx()] != nullptr);
142  assert( properties_[_h.idx()]->internal_type_name() == get_type_name<T>() );
143  PropertyT<T> *p = static_cast< PropertyT<T>* > (properties_[_h.idx()]);
144  assert(p != nullptr);
145  return *p;
146  }
147 
148 
149  template <class T> const PropertyT<T>& property(BasePropHandleT<T> _h) const
150  {
151  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
152  assert(properties_[_h.idx()] != nullptr);
153  assert( properties_[_h.idx()]->internal_type_name() == get_type_name<T>() );
154  PropertyT<T> *p = static_cast< PropertyT<T>* > (properties_[_h.idx()]);
155  assert(p != nullptr);
156  return *p;
157  }
158 
159 
160  template <class T> void remove(BasePropHandleT<T> _h)
161  {
162  assert(_h.idx() >= 0 && _h.idx() < (int)properties_.size());
163  delete properties_[_h.idx()];
164  properties_[_h.idx()] = nullptr;
165  }
166 
167 
168  void clear()
169  {
170  // Clear properties vector:
171  // Replaced the old version with new one
172  // which performs a swap to clear values and
173  // deallocate memory.
174 
175  // Old version (changed 22.07.09) {
176  // std::for_each(properties_.begin(), properties_.end(), Delete());
177  // }
178 
179  std::for_each(properties_.begin(), properties_.end(), ClearAll());
180  }
181 
182 
183  //---------------------------------------------------- synchronize properties
184 
185 /*
186  * In C++11 an beyond we can introduce more efficient and more legible
187  * implementations of the following methods.
188  */
189 #if ((defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
193  void reserve(size_t _n) const {
194  std::for_each(properties_.begin(), properties_.end(),
195  [_n](BaseProperty* p) { if (p) p->reserve(_n); });
196  }
197 
201  void resize(size_t _n) const {
202  std::for_each(properties_.begin(), properties_.end(),
203  [_n](BaseProperty* p) { if (p) p->resize(_n); });
204  }
205 
214  void resize_if_smaller(size_t _n) const {
215  std::for_each(properties_.begin(), properties_.end(),
216  [_n](BaseProperty* p) { if (p && p->n_elements() < _n) p->resize(_n); });
217  }
218 
223  void swap(size_t _i0, size_t _i1) const {
224  std::for_each(properties_.begin(), properties_.end(),
225  [_i0, _i1](BaseProperty* p) { if (p) p->swap(_i0, _i1); });
226  }
227 #else
231  void reserve(size_t _n) const {
232  std::for_each(properties_.begin(), properties_.end(), Reserve(_n));
233  }
234 
238  void resize(size_t _n) const {
239  std::for_each(properties_.begin(), properties_.end(), Resize(_n));
240  }
241 
250  void resize_if_smaller(size_t _n) const {
251  std::for_each(properties_.begin(), properties_.end(), ResizeIfSmaller(_n));
252  }
253 
258  void swap(size_t _i0, size_t _i1) const {
259  std::for_each(properties_.begin(), properties_.end(), Swap(_i0, _i1));
260  }
261 #endif
262 
263 
264 
265 protected: // generic add/get
266 
267  size_t _add( BaseProperty* _bp )
268  {
269  Properties::iterator p_it=properties_.begin(), p_end=properties_.end();
270  size_t idx=0;
271  for (; p_it!=p_end && *p_it!=nullptr; ++p_it, ++idx) {};
272  if (p_it==p_end) properties_.push_back(nullptr);
273  properties_[idx] = _bp;
274  return idx;
275  }
276 
277  BaseProperty& _property( size_t _idx )
278  {
279  assert( _idx < properties_.size());
280  assert( properties_[_idx] != nullptr);
281  BaseProperty *p = properties_[_idx];
282  assert( p != nullptr );
283  return *p;
284  }
285 
286  const BaseProperty& _property( size_t _idx ) const
287  {
288  assert( _idx < properties_.size());
289  assert( properties_[_idx] != nullptr);
290  BaseProperty *p = properties_[_idx];
291  assert( p != nullptr );
292  return *p;
293  }
294 
295 
296  typedef Properties::iterator iterator;
297  typedef Properties::const_iterator const_iterator;
298  iterator begin() { return properties_.begin(); }
299  iterator end() { return properties_.end(); }
300  const_iterator begin() const { return properties_.begin(); }
301  const_iterator end() const { return properties_.end(); }
302 
303  friend class BaseKernel;
304 
305 private:
306 
307  //-------------------------------------------------- synchronization functors
308 
309 #ifndef DOXY_IGNORE_THIS
310  struct Reserve
311  {
312  explicit Reserve(size_t _n) : n_(_n) {}
313  void operator()(BaseProperty* _p) const { if (_p) _p->reserve(n_); }
314  size_t n_;
315  };
316 
317  struct Resize
318  {
319  explicit Resize(size_t _n) : n_(_n) {}
320  void operator()(BaseProperty* _p) const { if (_p) _p->resize(n_); }
321  size_t n_;
322  };
323 
324  struct ResizeIfSmaller
325  {
326  explicit ResizeIfSmaller(size_t _n) : n_(_n) {}
327  void operator()(BaseProperty* _p) const { if (_p && _p->n_elements() < n_) _p->resize(n_); }
328  size_t n_;
329  };
330 
331  struct ClearAll
332  {
333  ClearAll() {}
334  void operator()(BaseProperty* _p) const { if (_p) _p->clear(); }
335  };
336 
337  struct Swap
338  {
339  Swap(size_t _i0, size_t _i1) : i0_(_i0), i1_(_i1) {}
340  void operator()(BaseProperty* _p) const { if (_p) _p->swap(i0_, i1_); }
341  size_t i0_, i1_;
342  };
343 
344  struct Delete
345  {
346  Delete() {}
347  void operator()(BaseProperty* _p) const { if (_p) delete _p; }
348  };
349 #endif
350 
351  Properties properties_;
352 };
353 
354 }//namespace OpenMesh
355 
356 #endif//OPENMESH_PROPERTYCONTAINER
357 
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
int idx() const
Get the underlying index of this handle.
Definition: Handles.hh:69
Abstract class defining the basic interface of a dynamic property.
Definition: BaseProperty.hh:61
Default property class for any type T.
Definition: Property.hh:93
Base property handle.
Definition: Property.hh:401
A a container for properties.
Definition: PropertyContainer.hh:59
void reserve(size_t _n) const
Reserves space for _n elements in all property vectors.
Definition: PropertyContainer.hh:231
void resize_if_smaller(size_t _n) const
Same as.
Definition: PropertyContainer.hh:250
void swap(size_t _i0, size_t _i1) const
Swaps the items with index _i0 and index _i1 in all property vectors.
Definition: PropertyContainer.hh:258
void resize(size_t _n) const
Resizes all property vectors to the specified size.
Definition: PropertyContainer.hh:238

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .