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 <OpenMesh/Core/Mesh/PolyConnectivity.hh>
48 #include <sstream>
49 #include <stdexcept>
50 #include <string>
51 
52 namespace OpenMesh {
53 
79 template<typename PROPTYPE, typename MeshT = int>
81 
82  public:
83  using Value = typename PROPTYPE::Value;
84  using value_type = typename PROPTYPE::value_type;
85  using Handle = typename PROPTYPE::Handle;
87  using Reference = typename PROPTYPE::reference;
88  using ConstReference = typename PROPTYPE::const_reference;
89 
90  private:
91  // Mesh properties (MPropHandleT<...>) are stored differently than the other properties.
92  // This class implements different behavior when copying or swapping data from one
93  // property manager to a another one.
94  template <typename PropertyManager2, typename PropHandleT>
95  struct StorageT;
96 
97  // specialization for Mesh Properties
98  template <typename PropertyManager2>
99  struct StorageT<PropertyManager2, MPropHandleT<Value>> {
100  static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
101  *to = *from;
102  }
103  static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
104  std::swap(*to, *from);
105  }
106  static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) {
107  return mesh.property(prop_handle);
108  }
109  static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) {
110  return mesh.property(prop_handle);
111  }
112  };
113 
114  // definition for other Mesh Properties
115  template <typename PropertyManager2, typename PropHandleT>
116  struct StorageT {
117  static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
118  from.copy_to(from.mesh_.template all_elements<Handle>(), to, to.mesh_.template all_elements<Handle>());
119  }
120  static void swap(PropertyManager<PROPTYPE, MeshT>& lhs, PropertyManager2& rhs) {
121  std::swap(lhs.mesh().property(lhs.prop_).data_vector(), rhs.mesh().property(rhs.prop_).data_vector());
122  // resize the property to the correct size
123  lhs.mesh().property(lhs.prop_).resize(lhs.mesh().template n_elements<Handle>());
124  rhs.mesh().property(rhs.prop_).resize(rhs.mesh().template n_elements<Handle>());
125  }
126  static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) {
127  return mesh.property(prop_handle, handle);
128  }
129  static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) {
130  return mesh.property(prop_handle, handle);
131  }
132  };
133 
134  using Storage = StorageT<Self, PROPTYPE>;
135 
136  public:
137 
157  OM_DEPRECATED("Use the constructor without parameter 'existing' instead. Check for existance with hasProperty") // As long as this overload exists, initial value must be first parameter due to ambiguity for properties of type bool
158  PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
159  if (existing) {
160  if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
161  std::ostringstream oss;
162  oss << "Requested property handle \"" << propname << "\" does not exist.";
163  throw std::runtime_error(oss.str());
164  }
165  } else {
166  PropertyManager::mesh().add_property(prop_, propname);
167  }
168  }
169 
178  PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
179  if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
180  PropertyManager::mesh().add_property(prop_, propname);
181  }
182  }
183 
194  PropertyManager(const Value& initial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
195  if (!mesh_.get_property_handle(prop_, propname)) {
196  PropertyManager::mesh().add_property(prop_, propname);
197  set_range(mesh_.all_elements<Handle>(), initial_value);
198  }
199  }
200 
208  PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
209  PropertyManager::mesh().add_property(prop_, name_);
210  }
211 
220  PropertyManager(const Value& initial_value, const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
221  PropertyManager::mesh().add_property(prop_, name_);
222  set_range(mesh_.all_elements<Handle>(), initial_value);
223  }
224 
233  PropertyManager(PolyConnectivity& mesh, PROPTYPE property_handle) : mesh_(mesh), prop_(property_handle), retain_(true), name_() {
234  }
235 
236  PropertyManager() = delete;
237 
238  PropertyManager(const PropertyManager& rhs)
239  :
240  mesh_(rhs.mesh_),
241  prop_(),
242  retain_(rhs.retain_),
243  name_(rhs.name_)
244  {
245  if (rhs.retain_) // named property -> create a property manager referring to the same
246  {
247  prop_ = rhs.prop_;
248  }
249  else // unnamed property -> create a property manager refering to a new property and copy the contents
250  {
251  PropertyManager::mesh().add_property(prop_, name_);
252  Storage::copy(rhs, *this);
253  }
254  }
255 
256 
263  {
264  PropertyManager result(this->mesh());
265  Storage::copy(*this, result);
266  return result;
267  }
268 
269  PropertyManager& operator=(const PropertyManager& rhs)
270  {
271  if (&mesh_ == &rhs.mesh_ && prop_ == rhs.prop_)
272  ; // nothing to do
273  else
274  Storage::copy(rhs, *this);
275  return *this;
276  }
277 
278  ~PropertyManager() {
279  deleteProperty();
280  }
281 
282  void swap(PropertyManager &rhs) {
283  // swap the data stored in the properties
284  Storage::swap(rhs, *this);
285  }
286 
287  static bool propertyExists(PolyConnectivity &mesh, const char *propname) {
288  PROPTYPE dummy;
289  return mesh.get_property_handle(dummy, propname);
290  }
291 
292  bool isValid() const { return prop_.is_valid(); }
293  operator bool() const { return isValid(); }
294 
295  const PROPTYPE &getRawProperty() const { return prop_; }
296 
297  const std::string &getName() const { return name_; }
298 
312  template <typename MeshType >
313  const MeshType& getMesh() const { return dynamic_cast<const MeshType&>(mesh_); }
314 
315  const MeshT& getMesh() const { return dynamic_cast<const MeshT&>(mesh_); }
316 
317 
323  OM_DEPRECATED("retain no longer has any effect. Instead, named properties are always retained, while unnamed ones are not.")
324  void retain(bool = true) {}
325 
330  :
331  mesh_(rhs.mesh_),
332  prop_(rhs.prop_),
333  retain_(rhs.retain_),
334  name_(rhs.name_)
335  {
336  if (!rhs.retain_)
337  rhs.prop_.invalidate(); // only invalidate unnamed properties
338  }
339 
343  PropertyManager& operator=(PropertyManager&& rhs)
344  {
345  if ((&mesh_ != &rhs.mesh_) || (prop_ != rhs.prop_))
346  {
347  if (rhs.retain_)
348  {
349  // retained properties cannot be invalidated. Copy instead
350  Storage::copy(rhs, *this);
351  }
352  else
353  {
354  // swap the data stored in the properties
355  Storage::swap(rhs, *this);
356  // remove the property from rhs
357  rhs.mesh().remove_property(rhs.prop_);
358  // invalidate prop_
359  rhs.prop_.invalidate();
360  }
361  }
362  return *this;
363  }
364 
372  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname) {
373  return PropertyManager(mesh, propname);
374  }
375 
385  template<typename PROP_VALUE, typename ITERATOR_TYPE>
386  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
387  const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
388  const PROP_VALUE &init_value) {
389  const bool exists = propertyExists(mesh, propname);
390  PropertyManager pm(mesh, propname, exists);
391  pm.retain();
392  if (!exists)
393  pm.set_range(begin, end, init_value);
394  return std::move(pm);
395  }
396 
406  template<typename PROP_VALUE, typename ITERATOR_RANGE>
407  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
408  const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
409  return createIfNotExists(
410  mesh, propname, range.begin(), range.end(), init_value);
411  }
412 
413 
426  typename PROPTYPE::reference& operator*() {
427  return mesh().mproperty(prop_)[0];
428  }
429 
442  typename PROPTYPE::const_reference& operator*() const {
443  return mesh().mproperty(prop_)[0];
444  }
445 
453  inline typename PROPTYPE::reference operator[] (Handle handle) {
454  return mesh().property(prop_, handle);
455  }
456 
464  inline typename PROPTYPE::const_reference operator[] (const Handle& handle) const {
465  return mesh().property(prop_, handle);
466  }
467 
475  inline typename PROPTYPE::reference operator() (const Handle& handle = Handle()) {
476 // return mesh().property(prop_, handle);
477  return Storage::access_property(mesh(), prop_, handle);
478  }
479 
487  inline typename PROPTYPE::const_reference operator() (const Handle& handle = Handle()) const {
488 // return mesh().property(prop_, handle);
489  return Storage::access_property_const(mesh(), prop_, handle);
490  }
491 
516  template<typename HandleTypeIterator, typename PROP_VALUE>
517  void set_range(HandleTypeIterator begin, HandleTypeIterator end,
518  const PROP_VALUE &value) {
519  for (; begin != end; ++begin)
520  (*this)[*begin] = value;
521  }
522 
523 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
524  template<typename HandleTypeIteratorRange, typename PROP_VALUE>
525  void set_range(const HandleTypeIteratorRange &range,
526  const PROP_VALUE &value) {
527  set_range(range.begin(), range.end(), value);
528  }
529 #endif
530 
545  template<typename HandleTypeIterator, typename PROPTYPE_2,
546  typename HandleTypeIterator_2>
547  void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
548  PropertyManager<PROPTYPE_2> &dst_propmanager,
549  HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
550 
551  for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
552  dst_propmanager[*dst_begin] = (*this)[*begin];
553  }
554  }
555 
556  template<typename RangeType, typename PROPTYPE_2,
557  typename RangeType_2>
558  void copy_to(const RangeType &range,
559  PropertyManager<PROPTYPE_2> &dst_propmanager,
560  const RangeType_2 &dst_range) const {
561  copy_to(range.begin(), range.end(), dst_propmanager,
562  dst_range.begin(), dst_range.end());
563  }
564 
565 
580  template<typename RangeType, typename RangeType_2>
581  static void copy(const char *prop_name,
582  PolyConnectivity &src_mesh, const RangeType &src_range,
583  PolyConnectivity &dst_mesh, const RangeType_2 &dst_range) {
584 
586  DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
587 
589  SrcPM src(src_mesh, prop_name, true);
590 
591  src.copy_to(src_range, dst, dst_range);
592  }
593 
594  private:
595  void deleteProperty() {
596  if (!retain_ && prop_.is_valid())
597  mesh().remove_property(prop_);
598  }
599 
600  PolyConnectivity& mesh() const
601  {
602  return const_cast<PolyConnectivity&>(mesh_);
603  }
604 
605  private:
606  const PolyConnectivity& mesh_;
607  PROPTYPE prop_;
608  bool retain_;
609  std::string name_;
610 };
611 
612 template <typename PropertyT>
614 {
615 public:
616  using Value = typename PropertyT::Value;
617  using value_type = typename PropertyT::value_type;
618  using Handle = typename PropertyT::Handle;
619 
620  ConstPropertyViewer(const PolyConnectivity& mesh, PropertyT property_handle)
621  :
622  mesh_(mesh),
623  prop_(property_handle)
624  {}
625 
626  inline const typename PropertyT::const_reference operator() (const Handle& handle)
627  {
628  return mesh_.property(prop_, handle);
629  }
630 
631  inline const typename PropertyT::const_reference operator[] (const Handle& handle)
632  {
633  return mesh_.property(prop_, handle);
634  }
635 
636 private:
637  const PolyConnectivity& mesh_;
638  PropertyT prop_;
639 };
640 
668 template<typename ElementT, typename T>
670 OM_DEPRECATED("Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name")
671 makeTemporaryProperty(PolyConnectivity &mesh, const char *propname) {
673 }
674 
699 template<typename ElementT, typename T>
703 }
704 
705 
727 template<typename ElementT, typename T>
728 bool
729 hasProperty(const PolyConnectivity &mesh, const char *propname) {
731  return mesh.get_property_handle(ph, propname);
732 }
733 
761 template<typename ElementT, typename T>
763 getProperty(PolyConnectivity &mesh, const char *propname) {
764  if (!hasProperty<ElementT, T>(mesh, propname))
765  {
766  std::ostringstream oss;
767  oss << "Requested property handle \"" << propname << "\" does not exist.";
768  throw std::runtime_error(oss.str());
769  }
771 }
772 
802 template<typename ElementT, typename T>
804 getOrMakeProperty(PolyConnectivity &mesh, const char *propname) {
805  return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>::createIfNotExists(mesh, propname);
806 }
807 
817 template<typename PROPTYPE>
818 OM_DEPRECATED("Use makeTemporaryProperty instead.")
819 PropertyManager<PROPTYPE> makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
820 {
821  return PropertyManager<PROPTYPE>(mesh, propname, false);
822 }
823 
836 template<typename PROPTYPE, typename MeshT = int>
837 OM_DEPRECATED("Use getProperty instead.")
838 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
839 {
840  return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
841 }
842 
851 template<typename PROPTYPE, typename MeshT = int>
852 OM_DEPRECATED("Use getOrMakeProperty instead.")
853 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
854 {
856 }
857 
869 template<typename PROPTYPE,
870  typename ITERATOR_TYPE, typename PROP_VALUE>
871 OM_DEPRECATED("Use getOrMakeProperty instead.")
873  PolyConnectivity &mesh, const char *propname,
874  const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
875  const PROP_VALUE &init_value) {
877  mesh, propname, begin, end, init_value);
878 }
879 
891 template<typename PROPTYPE,
892  typename ITERATOR_RANGE, typename PROP_VALUE>
893 OM_DEPRECATED("Use getOrMakeProperty instead.")
895  PolyConnectivity &mesh, const char *propname,
896  const ITERATOR_RANGE &range,
897  const PROP_VALUE &init_value) {
898  return makePropertyManagerFromExistingOrNew<PROPTYPE>(
899  mesh, propname, range.begin(), range.end(), init_value);
900 }
901 
902 
906 template<typename MeshT>
908 getPointsProperty(MeshT &mesh) {
909  return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
910 }
911 
915 template<typename MeshT>
917 getPointsProperty(const MeshT &mesh) {
919  return ConstPropertyViewer<PropType>(mesh, mesh.points_property_handle());
920 }
921 
922 template <typename HandleT, typename T>
924 
925 template <typename T>
927 
928 template <typename T>
930 
931 template <typename T>
933 
934 template <typename T>
936 
937 template <typename T>
939 
940 
941 } /* namespace OpenMesh */
942 #endif /* PROPERTYMANAGER_HH_ */
PROPTYPE::reference operator()(const Handle &handle=Handle())
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:475
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
You should not use this function directly.
Definition: BaseKernel.hh:254
Handle representing a vertex property.
Definition: Property.hh:484
PropertyManager< PROPTYPE > makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:819
PropertyManager< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(MeshT &mesh)
Definition: PropertyManager.hh:908
PropertyManager(const Value &initial_value, const PolyConnectivity &mesh)
Constructor.
Definition: PropertyManager.hh:220
This class is intended to manage the lifecycle of properties.
Definition: PropertyManager.hh:80
PropertyManager clone()
Create property manager referring to a copy of the current property.
Definition: PropertyManager.hh:262
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > makeTemporaryProperty(PolyConnectivity &mesh)
Definition: PropertyManager.hh:701
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
Conveniently set the property for an entire range of values.
Definition: PropertyManager.hh:517
PropertyT< T > & property(VPropHandleT< T > _ph)
In most cases you should use the convenient PropertyManager wrapper and use of this function should n...
Definition: BaseKernel.hh:310
PROPTYPE::reference operator[](Handle handle)
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:453
PROPTYPE::const_reference & operator*() const
Access the value of the encapsulated mesh property.
Definition: PropertyManager.hh:442
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:838
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getProperty(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:763
PropertyManager< PROPTYPE, MeshT > makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:853
static void copy(const char *prop_name, PolyConnectivity &src_mesh, const RangeType &src_range, PolyConnectivity &dst_mesh, const RangeType_2 &dst_range)
Copy the values of a property from a source range to a target range.
Definition: PropertyManager.hh:581
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getOrMakeProperty(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:804
PropertyManager(const Value &initial_value, PolyConnectivity &mesh, const char *propname)
Constructor.
Definition: PropertyManager.hh:194
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager< PROPTYPE_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:547
Definition: PropertyManager.hh:613
PropertyT< T > & mproperty(MPropHandleT< T > _ph)
In most cases you should use the convenient PropertyManager wrapper and use of this function should n...
Definition: BaseKernel.hh:346
Definition: HandleToPropHandle.hh:10
PROPTYPE::reference & operator*()
Get the mesh corresponding to the property.
Definition: PropertyManager.hh:426
Default property class for any type T.
Definition: Property.hh:89
void remove_property(VPropHandleT< T > &_ph)
You should not use this function directly.
Definition: BaseKernel.hh:194
bool hasProperty(const PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:729
Connectivity Class for polygonal meshes.
Definition: PolyConnectivity.hh:112
PropertyManager(const PolyConnectivity &mesh)
Constructor.
Definition: PropertyManager.hh:208
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > makeTemporaryProperty(PolyConnectivity &mesh, const char *propname)
Definition: PropertyManager.hh:671
PropertyManager(PolyConnectivity &mesh, const char *propname)
Constructor.
Definition: PropertyManager.hh:178
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
PropertyManager(PolyConnectivity &mesh, PROPTYPE property_handle)
Constructor.
Definition: PropertyManager.hh:233
ConstPropertyViewer< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(const MeshT &mesh)
Definition: PropertyManager.hh:917

Project OpenMesh, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .