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

| OpenMesh

PropertyManager.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 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
49 #ifndef PROPERTYMANAGER_HH_
50 #define PROPERTYMANAGER_HH_
51
52 #include <sstream>
53 #include <stdexcept>
54 #include <string>
55
56 namespace OpenMesh {
57
93 template<typename PROPTYPE, typename MeshT>
94 class PropertyManager {
95 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
96 public:
97 PropertyManager(const PropertyManager&) = delete;
98 PropertyManager& operator=(const PropertyManager&) = delete;
99 #else
100 private:
104 PropertyManager(const PropertyManager&);
105
109 PropertyManager& operator=(const PropertyManager&);
110 #endif
111
112 public:
130 PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
131 if (existing) {
132 if (!mesh_->get_property_handle(prop_, propname)) {
133 std::ostringstream oss;
134 oss << "Requested property handle \"" << propname << "\" does not exist.";
135 throw std::runtime_error(oss.str());
136 }
137 } else {
138 mesh_->add_property(prop_, propname);
139 }
140 }
141
142 PropertyManager() : mesh_(0), retain_(false) {
143 }
144
145 ~PropertyManager() {
146 deleteProperty();
147 }
148
149 void swap(PropertyManager &rhs) {
150 std::swap(mesh_, rhs.mesh_);
151 std::swap(prop_, rhs.prop_);
152 std::swap(retain_, rhs.retain_);
153 std::swap(name_, rhs.name_);
154 }
155
156 static bool propertyExists(MeshT &mesh, const char *propname) {
157 PROPTYPE dummy;
158 return mesh.get_property_handle(dummy, propname);
159 }
160
161 bool isValid() const { return mesh_ != 0; }
162 operator bool() const { return isValid(); }
163
164 const PROPTYPE &getRawProperty() const { return prop_; }
165
166 const std::string &getName() const { return name_; }
167
168 MeshT &getMesh() const { return *mesh_; }
169
170 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
171
173 typedef PropertyManager<PROPTYPE, MeshT> Proxy;
174
178 PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
179 rhs.retain_ = true;
180 }
181
185 PropertyManager &operator=(PropertyManager &&rhs) {
186 if (&rhs != this) {
187 deleteProperty();
188 mesh_ = rhs.mesh_;
189 prop_ = rhs.prop_;
190 retain_ = rhs.retain_;
191 name_ = rhs.name_;
192 rhs.retain_ = true;
193 }
194 return *this;
195 }
196
204 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
205 PROPTYPE dummy_prop;
206 PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
207 pm.retain();
208 return std::move(pm);
209 }
210
220 template<typename PROP_VALUE, typename ITERATOR_TYPE>
221 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
222 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
223 const PROP_VALUE &init_value) {
224 const bool exists = propertyExists(mesh, propname);
225 PropertyManager pm(mesh, propname, exists);
226 pm.retain();
227 if (!exists)
228 pm.set_range(begin, end, init_value);
229 return std::move(pm);
230 }
231
241 template<typename PROP_VALUE, typename ITERATOR_RANGE>
242 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
243 const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
244 return createIfNotExists(
245 mesh, propname, range.begin(), range.end(), init_value);
246 }
247
248 PropertyManager duplicate(const char *clone_name) {
249 PropertyManager pm(*mesh_, clone_name, false);
250 pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
251 return pm;
252 }
253
257 PropertyManager move() {
258 return std::move(*this);
259 }
260
261 #else
262 class Proxy {
263 private:
264 Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
265 mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
266 MeshT *mesh_;
267 PROPTYPE prop_;
268 bool retain_;
269 std::string name_;
270
271 friend class PropertyManager;
272 };
273
274 operator Proxy() {
275 Proxy p(mesh_, prop_, retain_, name_);
276 mesh_ = 0;
277 retain_ = true;
278 return p;
279 }
280
281 Proxy move() {
282 return (Proxy)*this;
283 }
284
285 PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}
286
287 PropertyManager &operator=(Proxy p) {
288 PropertyManager(p).swap(*this);
289 return *this;
290 }
291
299 static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
300 PROPTYPE dummy_prop;
301 PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
302 pm.retain();
303 return (Proxy)pm;
304 }
305
315 template<typename PROP_VALUE, typename ITERATOR_TYPE>
316 static Proxy createIfNotExists(MeshT &mesh, const char *propname,
317 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
318 const PROP_VALUE &init_value) {
319 const bool exists = propertyExists(mesh, propname);
320 PropertyManager pm(mesh, propname, exists);
321 pm.retain();
322 if (!exists)
323 pm.set_range(begin, end, init_value);
324 return (Proxy)pm;
325 }
326
327 Proxy duplicate(const char *clone_name) {
328 PropertyManager pm(*mesh_, clone_name, false);
329 pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
330 return (Proxy)pm;
331 }
332 #endif
333
340 inline void retain(bool doRetain = true) {
341 retain_ = doRetain;
342 }
343
347 inline PROPTYPE &operator* () {
348 return prop_;
349 }
350
354 inline const PROPTYPE &operator* () const {
355 return prop_;
356 }
357
365 template<typename HandleType>
366 inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
367 return mesh_->property(prop_, handle);
368 }
369
377 template<typename HandleType>
378 inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
379 return mesh_->property(prop_, handle);
380 }
381
406 template<typename HandleTypeIterator, typename PROP_VALUE>
407 void set_range(HandleTypeIterator begin, HandleTypeIterator end,
408 const PROP_VALUE &value) {
409 for (; begin != end; ++begin)
410 (*this)[*begin] = value;
411 }
412
413 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
414 template<typename HandleTypeIteratorRange, typename PROP_VALUE>
415 void set_range(const HandleTypeIteratorRange &range,
416 const PROP_VALUE &value) {
417 set_range(range.begin(), range.end(), value);
418 }
419 #endif
420
435 template<typename HandleTypeIterator, typename PROPTYPE_2,
436 typename MeshT_2, typename HandleTypeIterator_2>
437 void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
438 PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
439 HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
440
441 for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
442 dst_propmanager[*dst_begin] = (*this)[*begin];
443 }
444 }
445
446 template<typename RangeType, typename PROPTYPE_2,
447 typename MeshT_2, typename RangeType_2>
448 void copy_to(const RangeType &range,
449 PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
450 const RangeType_2 &dst_range) const {
451 copy_to(range.begin(), range.end(), dst_propmanager,
452 dst_range.begin(), dst_range.end());
453 }
454
469 template<typename RangeType, typename MeshT_2, typename RangeType_2>
470 static void copy(const char *prop_name,
471 MeshT &src_mesh, const RangeType &src_range,
472 MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {
473
474 typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
475 DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
476
477 typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
478 SrcPM src(src_mesh, prop_name, true);
479
480 src.copy_to(src_range, dst, dst_range);
481 }
482
483 private:
484 void deleteProperty() {
485 if (!retain_)
486 mesh_->remove_property(prop_);
487 }
488
489 private:
490 MeshT *mesh_;
491 PROPTYPE prop_;
492 bool retain_;
493 std::string name_;
494 };
495
503 template<typename PROPTYPE, typename MeshT>
504 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromNew(MeshT &mesh, const char *propname) {
505 return PropertyManager<PROPTYPE, MeshT>(mesh, propname, false);
506 }
507
518 template<typename PROPTYPE, typename MeshT>
519 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(MeshT &mesh, const char *propname) {
520 return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
521 }
522
529 template<typename PROPTYPE, typename MeshT>
530 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname) {
531 return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(mesh, propname);
532 }
533
545 template<typename PROPTYPE, typename MeshT,
546 typename ITERATOR_TYPE, typename PROP_VALUE>
547 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
548 MeshT &mesh, const char *propname,
549 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
550 const PROP_VALUE &init_value) {
551 return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(
552 mesh, propname, begin, end, init_value);
553 }
554
566 template<typename PROPTYPE, typename MeshT,
567 typename ITERATOR_RANGE, typename PROP_VALUE>
568 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
569 MeshT &mesh, const char *propname,
570 const ITERATOR_RANGE &range,
571 const PROP_VALUE &init_value) {
572 return makePropertyManagerFromExistingOrNew<PROPTYPE, MeshT>(
573 mesh, propname, range.begin(), range.end(), init_value);
574 }
575
576 } /* namespace OpenMesh */
577 #endif /* PROPERTYMANAGER_HH_ */
OpenMesh::PropertyManager::PropertyManager
PropertyManager(MeshT &mesh, const char *propname, bool existing=false)
Constructor.
Definition: PropertyManager.hh:130
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value)
Definition: PropertyManager.hh:568
OpenMesh::PropertyManager::operator[]
PROPTYPE::reference operator[](const HandleType &handle)
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:366
OpenMesh::PropertyManager::createIfNotExists
static Proxy createIfNotExists(MeshT &mesh, const char *propname)
Create a property manager for the supplied property and mesh.
Definition: PropertyManager.hh:299
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:64
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:530
OpenMesh::PropertyManager::copy_to
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager< PROPTYPE_2, MeshT_2 > &dst_propmanager, HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const
Conveniently transfer the values managed by one property manager onto the values managed by a differe...
Definition: PropertyManager.hh:437
OpenMesh::PropertyManager::set_range
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
Conveniently set the property for an entire range of values.
Definition: PropertyManager.hh:407
OpenMesh::PropertyManager::operator*
PROPTYPE & operator*()
Access the encapsulated property.
Definition: PropertyManager.hh:347
OpenMesh::PropertyManager::copy
static void copy(const char *prop_name, MeshT &src_mesh, const RangeType &src_range, MeshT_2 &dst_mesh, const RangeType_2 &dst_range)
Copy the values of a property from a source range to a target range.
Definition: PropertyManager.hh:470
OpenMesh::PropertyManager::retain
void retain(bool doRetain=true)
Disable lifecycle management for this property.
Definition: PropertyManager.hh:340
OpenMesh::PropertyManager::Proxy
Definition: PropertyManager.hh:262
OpenMesh::PropertyManager::makePropertyManagerFromExisting
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:519
OpenMesh::PropertyManager::makePropertyManagerFromNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:504
OpenMesh::PropertyManager::createIfNotExists
static Proxy createIfNotExists(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
Like createIfNotExists() with two parameters except, if the property doesn&#39;t exist, it is initialized with the supplied value over the supplied range after creation.
Definition: PropertyManager.hh:316
OpenMesh::PropertyManager
This class is intended to manage the lifecycle of properties.
Definition: PropertyManager.hh:94
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
Definition: PropertyManager.hh:547