| 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 #ifndef PROPERTYMANAGER_HH_
43 #define PROPERTYMANAGER_HH_
44
45 #include <OpenMesh/Core/System/config.h>
46 #include <OpenMesh/Core/Utils/HandleToPropHandle.hh>
47 #include <sstream>
48 #include <stdexcept>
49 #include <string>
50
51 namespace OpenMesh {
52
76 template<typename PROPTYPE, typename MeshT>
77 class PropertyManager {
78 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
79 public:
80 PropertyManager(const PropertyManager&) = delete;
81 PropertyManager& operator=(const PropertyManager&) = delete;
82 #else
83 private:
87 PropertyManager(const PropertyManager&);
88
92 PropertyManager& operator=(const PropertyManager&);
93 #endif
94
95 public:
113 PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
114 if (existing) {
115 if (!mesh_->get_property_handle(prop_, propname)) {
116 std::ostringstream oss;
117 oss << "Requested property handle \"" << propname << "\" does not exist.";
118 throw std::runtime_error(oss.str());
119 }
120 } else {
121 mesh_->add_property(prop_, propname);
122 }
123 }
124
125 PropertyManager() : mesh_(0), retain_(false) {
126 }
127
128 ~PropertyManager() {
129 deleteProperty();
130 }
131
132 void swap(PropertyManager &rhs) {
133 std::swap(mesh_, rhs.mesh_);
134 std::swap(prop_, rhs.prop_);
135 std::swap(retain_, rhs.retain_);
136 std::swap(name_, rhs.name_);
137 }
138
139 static bool propertyExists(MeshT &mesh, const char *propname) {
140 PROPTYPE dummy;
141 return mesh.get_property_handle(dummy, propname);
142 }
143
144 bool isValid() const { return mesh_ != 0; }
145 operator bool() const { return isValid(); }
146
147 const PROPTYPE &getRawProperty() const { return prop_; }
148
149 const std::string &getName() const { return name_; }
150
151 MeshT &getMesh() const { return *mesh_; }
152
153 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
154
156 typedef PropertyManager<PROPTYPE, MeshT> Proxy;
157
161 PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
162 rhs.retain_ = true;
163 }
164
168 PropertyManager &operator=(PropertyManager &&rhs) {
169 if (&rhs != this) {
170 deleteProperty();
171 mesh_ = rhs.mesh_;
172 prop_ = rhs.prop_;
173 retain_ = rhs.retain_;
174 name_ = rhs.name_;
175 rhs.retain_ = true;
176 }
177 return *this;
178 }
179
187 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
188 PROPTYPE dummy_prop;
189 PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
190 pm.retain();
191 return std::move(pm);
192 }
193
203 template<typename PROP_VALUE, typename ITERATOR_TYPE>
204 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
205 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
206 const PROP_VALUE &init_value) {
207 const bool exists = propertyExists(mesh, propname);
208 PropertyManager pm(mesh, propname, exists);
209 pm.retain();
210 if (!exists)
211 pm.set_range(begin, end, init_value);
212 return std::move(pm);
213 }
214
224 template<typename PROP_VALUE, typename ITERATOR_RANGE>
225 static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
226 const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
227 return createIfNotExists(
228 mesh, propname, range.begin(), range.end(), init_value);
229 }
230
231 PropertyManager duplicate(const char *clone_name) {
232 PropertyManager pm(*mesh_, clone_name, false);
233 pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
234 return pm;
235 }
236
240 PropertyManager move() {
241 return std::move(*this);
242 }
243
244 #else
245 class Proxy {
246 private:
247 Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
248 mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
249 MeshT *mesh_;
250 PROPTYPE prop_;
251 bool retain_;
252 std::string name_;
253
254 friend class PropertyManager;
255 };
256
257 operator Proxy() {
258 Proxy p(mesh_, prop_, retain_, name_);
259 mesh_ = 0;
260 retain_ = true;
261 return p;
262 }
263
264 Proxy move() {
265 return (Proxy)*this;
266 }
267
268 PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}
269
270 PropertyManager &operator=(Proxy p) {
271 PropertyManager(p).swap(*this);
272 return *this;
273 }
274
282 static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
283 PROPTYPE dummy_prop;
284 PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
285 pm.retain();
286 return (Proxy)pm;
287 }
288
298 template<typename PROP_VALUE, typename ITERATOR_TYPE>
299 static Proxy createIfNotExists(MeshT &mesh, const char *propname,
300 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
301 const PROP_VALUE &init_value) {
302 const bool exists = propertyExists(mesh, propname);
303 PropertyManager pm(mesh, propname, exists);
304 pm.retain();
305 if (!exists)
306 pm.set_range(begin, end, init_value);
307 return (Proxy)pm;
308 }
309
310 Proxy duplicate(const char *clone_name) {
311 PropertyManager pm(*mesh_, clone_name, false);
312 pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
313 return (Proxy)pm;
314 }
315 #endif
316
323 inline void retain(bool doRetain = true) {
324 retain_ = doRetain;
325 }
326
330 inline PROPTYPE &operator* () {
331 return prop_;
332 }
333
337 inline const PROPTYPE &operator* () const {
338 return prop_;
339 }
340
348 template<typename HandleType>
349 inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
350 return mesh_->property(prop_, handle);
351 }
352
360 template<typename HandleType>
361 inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
362 return mesh_->property(prop_, handle);
363 }
364
389 template<typename HandleTypeIterator, typename PROP_VALUE>
390 void set_range(HandleTypeIterator begin, HandleTypeIterator end,
391 const PROP_VALUE &value) {
392 for (; begin != end; ++begin)
393 (*this)[*begin] = value;
394 }
395
396 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
397 template<typename HandleTypeIteratorRange, typename PROP_VALUE>
398 void set_range(const HandleTypeIteratorRange &range,
399 const PROP_VALUE &value) {
400 set_range(range.begin(), range.end(), value);
401 }
402 #endif
403
418 template<typename HandleTypeIterator, typename PROPTYPE_2,
419 typename MeshT_2, typename HandleTypeIterator_2>
420 void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
421 PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
422 HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
423
424 for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
425 dst_propmanager[*dst_begin] = (*this)[*begin];
426 }
427 }
428
429 template<typename RangeType, typename PROPTYPE_2,
430 typename MeshT_2, typename RangeType_2>
431 void copy_to(const RangeType &range,
432 PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
433 const RangeType_2 &dst_range) const {
434 copy_to(range.begin(), range.end(), dst_propmanager,
435 dst_range.begin(), dst_range.end());
436 }
437
452 template<typename RangeType, typename MeshT_2, typename RangeType_2>
453 static void copy(const char *prop_name,
454 MeshT &src_mesh, const RangeType &src_range,
455 MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {
456
457 typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
458 DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
459
460 typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
461 SrcPM src(src_mesh, prop_name, true);
462
463 src.copy_to(src_range, dst, dst_range);
464 }
465
466 private:
467 void deleteProperty() {
468 if (!retain_)
469 mesh_->remove_property(prop_);
470 }
471
472 private:
473 MeshT *mesh_;
474 PROPTYPE prop_;
475 bool retain_;
476 std::string name_;
477 };
478
505 template<typename ElementT, typename T, typename MeshT>
506 PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
507 makeTemporaryProperty(MeshT &mesh, const char *propname = "") {
508 return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>(mesh, propname, false);
509 }
510
539 template<typename ElementT, typename T, typename MeshT>
540 PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
541 getProperty(MeshT &mesh, const char *propname) {
542 return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>(mesh, propname, true);
543 }
544
575 template<typename ElementT, typename T, typename MeshT>
576 PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
577 getOrMakeProperty(MeshT &mesh, const char *propname) {
578 return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>::createIfNotExists(mesh, propname);
579 }
580
590 template<typename PROPTYPE, typename MeshT>
591 OM_DEPRECATED("Use makeTemporaryProperty instead.")
592 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromNew(MeshT &mesh, const char *propname)
593 {
594 return PropertyManager<PROPTYPE, MeshT>(mesh, propname, false);
595 }
596
609 template<typename PROPTYPE, typename MeshT>
610 OM_DEPRECATED("Use getProperty instead.")
611 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
612 {
613 return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
614 }
615
624 template<typename PROPTYPE, typename MeshT>
625 OM_DEPRECATED("Use getOrMakeProperty instead.")
626 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
627 {
628 return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(mesh, propname);
629 }
630
642 template<typename PROPTYPE, typename MeshT,
643 typename ITERATOR_TYPE, typename PROP_VALUE>
644 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
645 MeshT &mesh, const char *propname,
646 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
647 const PROP_VALUE &init_value) {
648 return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(
649 mesh, propname, begin, end, init_value);
650 }
651
663 template<typename PROPTYPE, typename MeshT,
664 typename ITERATOR_RANGE, typename PROP_VALUE>
665 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
666 MeshT &mesh, const char *propname,
667 const ITERATOR_RANGE &range,
668 const PROP_VALUE &init_value) {
669 return makePropertyManagerFromExistingOrNew<PROPTYPE, MeshT>(
670 mesh, propname, range.begin(), range.end(), init_value);
671 }
672
673 } /* namespace OpenMesh */
674 #endif /* PROPERTYMANAGER_HH_ */
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:453
OpenMesh::PropertyManager
This class is intended to manage the lifecycle of properties.
Definition: PropertyManager.hh:77
OpenMesh::PropertyManager::makePropertyManagerFromExisting
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:611
OpenMesh::PropertyManager::Proxy
Definition: PropertyManager.hh:245
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:390
OpenMesh::PropertyManager::getProperty
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > getProperty(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:541
OpenMesh::PropertyManager::operator[]
PROPTYPE::reference operator[](const HandleType &handle)
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:349
OpenMesh::PropertyManager::createIfNotExists
static Proxy createIfNotExists(MeshT &mesh, const char *propname)
Create a property manager for the supplied property and mesh.
Definition: PropertyManager.hh:282
OpenMesh::PropertyManager::makePropertyManagerFromNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:592
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
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:299
OpenMesh::PropertyManager::makeTemporaryProperty
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > makeTemporaryProperty(MeshT &mesh, const char *propname="")
Definition: PropertyManager.hh:507
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:644
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:626
OpenMesh::PropertyManager::operator*
PROPTYPE & operator*()
Access the encapsulated property.
Definition: PropertyManager.hh:330
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:420
OpenMesh::PropertyManager::makePropertyManagerFromExistingOrNew
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value)
Definition: PropertyManager.hh:665
OpenMesh::PropertyManager::getOrMakeProperty
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > getOrMakeProperty(MeshT &mesh, const char *propname)
Definition: PropertyManager.hh:577
OpenMesh::PropertyManager::retain
void retain(bool doRetain=true)
Disable lifecycle management for this property.
Definition: PropertyManager.hh:323
OpenMesh::PropertyManager::PropertyManager
PropertyManager(MeshT &mesh, const char *propname, bool existing=false)
Constructor.
Definition: PropertyManager.hh:113