| OpenMesh

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 =========================================================
62 class PropertyContainer
63 {
64 public:
65
66 //-------------------------------------------------- constructor / destructor
67
68 PropertyContainer() {}
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
OpenMesh::PropertyContainer::resize_if_smaller
void resize_if_smaller(size_t _n) const
Same as.
Definition: PropertyContainer.hh:263
OpenMesh::BaseKernel
This class provides low-level property management like adding/removing properties and access to prope...
Definition: BaseKernel.hh:97
OpenMesh::PropertyContainer::swap
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:271
OpenMesh::BaseProperty::resize
virtual void resize(size_t _n)=0
Resize storage to hold n elements.
OpenMesh::PropertyContainer
A a container for properties.
Definition: PropertyContainer.hh:62
OpenMesh::BaseProperty
Abstract class defining the basic interface of a dynamic property.
Definition: BaseProperty.hh:60
OpenMesh::PropertyContainer::resize
void resize(size_t _n) const
Resizes all property vectors to the specified size.
Definition: PropertyContainer.hh:251
OpenMesh::BaseProperty::reserve
virtual void reserve(size_t _n)=0
Reserve memory for n elements.
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::BaseHandle::idx
int idx() const
Get the underlying index of this handle.
Definition: Handles.hh:69
OpenMesh::PropertyContainer::reserve
void reserve(size_t _n) const
Reserves space for _n elements in all property vectors.
Definition: PropertyContainer.hh:244
OpenMesh::BaseProperty::n_elements
virtual size_t n_elements() const =0
Number of elements in property.
OpenMesh::BasePropHandleT
Base property handle.
Definition: Property.hh:466
OpenMesh::BaseProperty::clear
virtual void clear()=0
Clear all elements and free memory.
OpenMesh::PropertyT
Default property class for any type T.
Definition: Property.hh:89
OpenMesh::BaseProperty::swap
virtual void swap(size_t _i0, size_t _i1)=0
Let two elements swap their storage place.