Developer Documentation
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 
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>
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:
88 
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 
157 
161  PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
162  rhs.retain_ = true;
163  }
164 
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 
458  DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
459 
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>
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>
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 {
629 }
630 
642 template<typename PROPTYPE, typename MeshT,
643  typename ITERATOR_TYPE, typename PROP_VALUE>
645  MeshT &mesh, const char *propname,
646  const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
647  const PROP_VALUE &init_value) {
649  mesh, propname, begin, end, init_value);
650 }
651 
663 template<typename PROPTYPE, typename MeshT,
664  typename ITERATOR_RANGE, typename PROP_VALUE>
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_ */
PropertyManager(MeshT &mesh, const char *propname, bool existing=false)
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname, const ITERATOR_RANGE &range, const PROP_VALUE &init_value)
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > makeTemporaryProperty(MeshT &mesh, const char *propname="")
static Proxy createIfNotExists(MeshT &mesh, const char *propname)
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > getOrMakeProperty(MeshT &mesh, const char *propname)
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
static void copy(const char *prop_name, MeshT &src_mesh, const RangeType &src_range, MeshT_2 &dst_mesh, const RangeType_2 &dst_range)
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager< PROPTYPE_2, MeshT_2 > &dst_propmanager, HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const
PropertyManager & operator=(const PropertyManager &)
void retain(bool doRetain=true)
Disable lifecycle management for this property.
PROPTYPE::reference operator[](const HandleType &handle)
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
PropertyManager< typename HandleToPropHandle< ElementT, T >::type, MeshT > getProperty(MeshT &mesh, const char *propname)
static Proxy createIfNotExists(MeshT &mesh, const char *propname, const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end, const PROP_VALUE &init_value)
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromNew(MeshT &mesh, const char *propname)