OpenMesh: OpenMesh/Core/Utils/PropertyContainer.hh Source File

| 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 =========================================================
58 class PropertyContainer
59 {
60 public:
61
62 //-------------------------------------------------- constructor / destructor
63
64 PropertyContainer() {}
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
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::BaseProperty
Abstract class defining the basic interface of a dynamic property.
Definition: BaseProperty.hh:61
OpenMesh::PropertyT
Default property class for any type T.
Definition: Property.hh:93
OpenMesh::BasePropHandleT
Base property handle.
Definition: Property.hh:401
OpenMesh::PropertyContainer
A a container for properties.
Definition: PropertyContainer.hh:59
OpenMesh::PropertyContainer::reserve
void reserve(size_t _n) const
Reserves space for _n elements in all property vectors.
Definition: PropertyContainer.hh:231
OpenMesh::PropertyContainer::resize_if_smaller
void resize_if_smaller(size_t _n) const
Same as.
Definition: PropertyContainer.hh:250
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:258
OpenMesh::PropertyContainer::resize
void resize(size_t _n) const
Resizes all property vectors to the specified size.
Definition: PropertyContainer.hh:238