OpenMesh
PropertyManager.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 #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 
75 template<typename PROPTYPE, typename MeshT = int>
77 
78  public:
79  using Value = typename PROPTYPE::Value;
80  using value_type = typename PROPTYPE::value_type;
81  using Handle = typename PROPTYPE::Handle;
83  using Reference = typename PROPTYPE::reference;
84  using ConstReference = typename PROPTYPE::const_reference;
85 
86  private:
87  // Mesh properties (MPropHandleT<...>) are stored differently than the other properties.
88  // This class implements different behavior when initializing a property or when
89  // copying or swapping data from one property manager to a another one.
90  template <typename PropertyManager2, typename PropHandleT>
91  struct StorageT;
92 
93  // specialization for Mesh Properties
94  template <typename PropertyManager2>
95  struct StorageT<PropertyManager2, MPropHandleT<Value>> {
96  static void initialize(PropertyManager<PROPTYPE, MeshT>& pm, const Value& initial_value ) {
97  pm() = initial_value;
98  }
99  static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
100  *to = *from;
101  }
102  static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
103  std::swap(*to, *from);
104  }
105  static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) {
106  return mesh.property(prop_handle);
107  }
108  static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle&) {
109  return mesh.property(prop_handle);
110  }
111  };
112 
113  // definition for other Mesh Properties
114  template <typename PropertyManager2, typename PropHandleT>
115  struct StorageT {
116  static void initialize(PropertyManager<PROPTYPE, MeshT>& pm, const Value& initial_value ) {
117  pm.set_range(pm.mesh_.template all_elements<Handle>(), initial_value);
118  }
119  static void copy(const PropertyManager& from, PropertyManager2& to) {
120  from.copy_to(from.mesh_.template all_elements<Handle>(), to, to.mesh_.template all_elements<Handle>());
121  }
122  static void swap(PropertyManager& lhs, PropertyManager2& rhs) {
123  std::swap(lhs.mesh().property(lhs.prop_).data_vector(), rhs.mesh().property(rhs.prop_).data_vector());
124  // resize the property to the correct size
125  lhs.mesh().property(lhs.prop_).resize(lhs.mesh().template n_elements<Handle>());
126  rhs.mesh().property(rhs.prop_).resize(rhs.mesh().template n_elements<Handle>());
127  }
128  static ConstReference access_property_const(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) {
129  return mesh.property(prop_handle, handle);
130  }
131  static Reference access_property(PolyConnectivity& mesh, const PROPTYPE& prop_handle, const Handle& handle) {
132  return mesh.property(prop_handle, handle);
133  }
134  };
135 
136  using Storage = StorageT<Self, PROPTYPE>;
137 
138  public:
139 
159  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
160  PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
161  if (existing) {
162  if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
163  std::ostringstream oss;
164  oss << "Requested property handle \"" << propname << "\" does not exist.";
165  throw std::runtime_error(oss.str());
166  }
167  } else {
168  PropertyManager::mesh().add_property(prop_, propname);
169  }
170  }
171 
180  PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
181  if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
182  PropertyManager::mesh().add_property(prop_, propname);
183  }
184  }
185 
196  PropertyManager(const Value& initial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
197  if (!mesh_.get_property_handle(prop_, propname)) {
198  PropertyManager::mesh().add_property(prop_, propname);
199  Storage::initialize(*this, initial_value);
200  }
201  }
202 
210  explicit PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
211  PropertyManager::mesh().add_property(prop_, name_);
212  }
213 
222  PropertyManager(const Value& initial_value, const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
223  PropertyManager::mesh().add_property(prop_, name_);
224  Storage::initialize(*this, initial_value);
225  }
226 
235  PropertyManager(PolyConnectivity& mesh, PROPTYPE property_handle) : mesh_(mesh), prop_(property_handle), retain_(true), name_() {
236  }
237 
238  PropertyManager() = delete;
239 
240  PropertyManager(const PropertyManager& rhs)
241  :
242  mesh_(rhs.mesh_),
243  prop_(),
244  retain_(rhs.retain_),
245  name_(rhs.name_)
246  {
247  if (rhs.retain_) // named property -> create a property manager referring to the same
248  {
249  prop_ = rhs.prop_;
250  }
251  else // unnamed property -> create a property manager refering to a new property and copy the contents
252  {
253  PropertyManager::mesh().add_property(prop_, name_);
254  Storage::copy(rhs, *this);
255  }
256  }
257 
258 
265  {
266  PropertyManager result(this->mesh());
267  Storage::copy(*this, result);
268  return result;
269  }
270 
271  PropertyManager& operator=(const PropertyManager& rhs)
272  {
273  if (&mesh_ == &rhs.mesh_ && prop_ == rhs.prop_)
274  ; // nothing to do
275  else
276  Storage::copy(rhs, *this);
277  return *this;
278  }
279 
280  ~PropertyManager() {
281  deleteProperty();
282  }
283 
284  void swap(PropertyManager &rhs) {
285  // swap the data stored in the properties
286  Storage::swap(rhs, *this);
287  }
288 
289  static bool propertyExists(PolyConnectivity &mesh, const char *propname) {
290  PROPTYPE dummy;
291  return mesh.get_property_handle(dummy, propname);
292  }
293 
294  bool isValid() const { return prop_.is_valid(); }
295  operator bool() const { return isValid(); }
296 
297  const PROPTYPE &getRawProperty() const { return prop_; }
298 
299  const std::string &getName() const { return name_; }
300 
314  template <typename MeshType >
315  const MeshType& getMesh() const { return dynamic_cast<const MeshType&>(mesh_); }
316 
317  const MeshT& getMesh() const { return dynamic_cast<const MeshT&>(mesh_); }
318 
319 
325  OM_DEPRECATED("retain no longer has any effect. Instead, named properties are always retained, while unnamed ones are not.")
326  void retain(bool = true) {}
327 
331  PropertyManager(PropertyManager &&rhs)
332  :
333  mesh_(rhs.mesh_),
334  prop_(rhs.prop_),
335  retain_(rhs.retain_),
336  name_(rhs.name_)
337  {
338  if (!rhs.retain_)
339  rhs.prop_.invalidate(); // only invalidate unnamed properties
340  }
341 
345  PropertyManager& operator=(PropertyManager&& rhs)
346  {
347  if ((&mesh_ != &rhs.mesh_) || (prop_ != rhs.prop_))
348  {
349  if (rhs.retain_)
350  {
351  // retained properties cannot be invalidated. Copy instead
352  Storage::copy(rhs, *this);
353  }
354  else
355  {
356  // swap the data stored in the properties
357  Storage::swap(rhs, *this);
358  // remove the property from rhs
359  rhs.mesh().remove_property(rhs.prop_);
360  // invalidate prop_
361  rhs.prop_.invalidate();
362  }
363  }
364  return *this;
365  }
366 
374  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname) {
375  return PropertyManager(mesh, propname);
376  }
377 
387  template<typename PROP_VALUE, typename ITERATOR_TYPE>
388  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
389  const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
390  const PROP_VALUE &init_value) {
391  const bool exists = propertyExists(mesh, propname);
392  PropertyManager pm(mesh, propname, exists);
393  pm.retain();
394  if (!exists)
395  pm.set_range(begin, end, init_value);
396  return std::move(pm);
397  }
398 
408  template<typename PROP_VALUE, typename ITERATOR_RANGE>
409  static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
410  const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
411  return createIfNotExists(
412  mesh, propname, range.begin(), range.end(), init_value);
413  }
414 
415 
428  typename PROPTYPE::reference& operator*() {
429  return mesh().mproperty(prop_)[0];
430  }
431 
444  typename PROPTYPE::const_reference& operator*() const {
445  return mesh().mproperty(prop_)[0];
446  }
447 
455  inline typename PROPTYPE::reference operator[] (Handle handle) {
456  return mesh().property(prop_, handle);
457  }
458 
466  inline typename PROPTYPE::const_reference operator[] (const Handle& handle) const {
467  return mesh().property(prop_, handle);
468  }
469 
477  inline typename PROPTYPE::reference operator() (const Handle& handle = Handle()) {
478 // return mesh().property(prop_, handle);
479  return Storage::access_property(mesh(), prop_, handle);
480  }
481 
489  inline typename PROPTYPE::const_reference operator() (const Handle& handle = Handle()) const {
490 // return mesh().property(prop_, handle);
491  return Storage::access_property_const(mesh(), prop_, handle);
492  }
493 
518  template<typename HandleTypeIterator, typename PROP_VALUE>
519  void set_range(HandleTypeIterator begin, HandleTypeIterator end,
520  const PROP_VALUE &value) {
521  for (; begin != end; ++begin)
522  (*this)[*begin] = value;
523  }
524 
525 #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
526  template<typename HandleTypeIteratorRange, typename PROP_VALUE>
527  void set_range(const HandleTypeIteratorRange &range,
528  const PROP_VALUE &value) {
529  set_range(range.begin(), range.end(), value);
530  }
531 #endif
532 
547  template<typename HandleTypeIterator, typename PropertyManager2,
548  typename HandleTypeIterator2>
549  void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
550  PropertyManager2 &dst_propmanager,
551  HandleTypeIterator2 dst_begin, HandleTypeIterator2 dst_end) const {
552 
553  for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
554  dst_propmanager[*dst_begin] = (*this)[*begin];
555  }
556  }
557 
558  template<typename RangeType, typename PropertyManager2,
559  typename RangeType2>
560  void copy_to(const RangeType &range,
561  PropertyManager2 &dst_propmanager,
562  const RangeType2 &dst_range) const {
563  copy_to(range.begin(), range.end(), dst_propmanager,
564  dst_range.begin(), dst_range.end());
565  }
566 
567 
582  template<typename RangeType, typename RangeType2>
583  static void copy(const char *prop_name,
584  PolyConnectivity &src_mesh, const RangeType &src_range,
585  PolyConnectivity &dst_mesh, const RangeType2 &dst_range) {
586 
588  DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
589 
591  SrcPM src(src_mesh, prop_name, true);
592 
593  src.copy_to(src_range, dst, dst_range);
594  }
595 
602  void set_persistent(bool _persistence = true)
603  {
604  mesh().property(getRawProperty()).set_persistent(_persistence);
605  }
606 
607  private:
608  void deleteProperty() {
609  if (!retain_ && prop_.is_valid())
610  mesh().remove_property(prop_);
611  }
612 
613  PolyConnectivity& mesh() const
614  {
615  return const_cast<PolyConnectivity&>(mesh_);
616  }
617 
618  private:
619  const PolyConnectivity& mesh_;
620  PROPTYPE prop_;
621  bool retain_;
622  std::string name_;
623 };
624 
625 template <typename PropertyT>
627 {
628 public:
629  using Value = typename PropertyT::Value;
630  using value_type = typename PropertyT::value_type;
631  using Handle = typename PropertyT::Handle;
632 
633  ConstPropertyViewer(const PolyConnectivity& mesh, const PropertyT& property_handle)
634  :
635  mesh_(mesh),
636  prop_(property_handle)
637  {}
638 
639  inline const typename PropertyT::const_reference operator() (const Handle& handle)
640  {
641  return mesh_.property(prop_, handle);
642  }
643 
644  inline const typename PropertyT::const_reference operator[] (const Handle& handle)
645  {
646  return mesh_.property(prop_, handle);
647  }
648 
649 private:
650  const PolyConnectivity& mesh_;
651  PropertyT prop_;
652 };
653 
681 template<typename ElementT, typename T>
683 OM_DEPRECATED("Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name")
684 makeTemporaryProperty(PolyConnectivity &mesh, const char *propname) {
686 }
687 
712 template<typename ElementT, typename T>
716 }
717 
718 
740 template<typename ElementT, typename T>
741 bool
742 hasProperty(const PolyConnectivity &mesh, const char *propname) {
744  return mesh.get_property_handle(ph, propname);
745 }
746 
774 template<typename ElementT, typename T>
776 getProperty(PolyConnectivity &mesh, const char *propname) {
777  if (!hasProperty<ElementT, T>(mesh, propname))
778  {
779  std::ostringstream oss;
780  oss << "Requested property handle \"" << propname << "\" does not exist.";
781  throw std::runtime_error(oss.str());
782  }
784 }
785 
815 template<typename ElementT, typename T>
817 getOrMakeProperty(PolyConnectivity &mesh, const char *propname) {
818  return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>::createIfNotExists(mesh, propname);
819 }
820 
830 template<typename PROPTYPE>
831 OM_DEPRECATED("Use makeTemporaryProperty instead.")
832 PropertyManager<PROPTYPE> makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
833 {
834  return PropertyManager<PROPTYPE>(mesh, propname, false);
835 }
836 
849 template<typename PROPTYPE, typename MeshT = int>
850 OM_DEPRECATED("Use getProperty instead.")
851 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
852 {
853  return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
854 }
855 
864 template<typename PROPTYPE, typename MeshT = int>
865 OM_DEPRECATED("Use getOrMakeProperty instead.")
866 PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
867 {
869 }
870 
882 template<typename PROPTYPE,
883  typename ITERATOR_TYPE, typename PROP_VALUE>
884 OM_DEPRECATED("Use getOrMakeProperty instead.")
885 PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
886  PolyConnectivity &mesh, const char *propname,
887  const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
888  const PROP_VALUE &init_value) {
890  mesh, propname, begin, end, init_value);
891 }
892 
904 template<typename PROPTYPE,
905  typename ITERATOR_RANGE, typename PROP_VALUE>
906 OM_DEPRECATED("Use getOrMakeProperty instead.")
907 PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
908  PolyConnectivity &mesh, const char *propname,
909  const ITERATOR_RANGE &range,
910  const PROP_VALUE &init_value) {
911  return makePropertyManagerFromExistingOrNew<PROPTYPE>(
912  mesh, propname, range.begin(), range.end(), init_value);
913 }
914 
915 
919 template<typename MeshT>
921 getPointsProperty(MeshT &mesh) {
922  return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
923 }
924 
928 template<typename MeshT>
930 getPointsProperty(const MeshT &mesh) {
932  return ConstPropertyViewer<PropType>(mesh, mesh.points_property_handle());
933 }
934 
935 template <typename HandleT, typename T>
937 
938 template <typename T>
940 
941 template <typename T>
943 
944 template <typename T>
946 
947 template <typename T>
949 
950 template <typename T>
952 
953 
954 } /* namespace OpenMesh */
955 #endif /* PROPERTYMANAGER_HH_ */
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
void remove_property(VPropHandleT< T > &_ph)
You should not use this function directly.
Definition: BaseKernel.hh:194
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
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
You should not use this function directly.
Definition: BaseKernel.hh:254
Connectivity Class for polygonal meshes.
Definition: PolyConnectivity.hh:115
Definition: HandleToPropHandle.hh:10
Default property class for any type T.
Definition: Property.hh:93
Handle representing a vertex property.
Definition: Property.hh:417
Handle representing a mesh property.
Definition: Property.hh:477
This class is intended to manage the lifecycle of properties.
Definition: PropertyManager.hh:76
PROPTYPE::reference & operator*()
Get the mesh corresponding to the property.
Definition: PropertyManager.hh:428
static void copy(const char *prop_name, PolyConnectivity &src_mesh, const RangeType &src_range, PolyConnectivity &dst_mesh, const RangeType2 &dst_range)
Copy the values of a property from a source range to a target range.
Definition: PropertyManager.hh:583
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
Conveniently set the property for an entire range of values.
Definition: PropertyManager.hh:519
PropertyManager(const Value &initial_value, PolyConnectivity &mesh, const char *propname)
Constructor.
Definition: PropertyManager.hh:196
ConstPropertyViewer< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(const MeshT &mesh)
Returns a convenience wrapper around the points property of a mesh that only allows const access.
Definition: PropertyManager.hh:930
PropertyManager(PolyConnectivity &mesh, const char *propname, bool existing)
Definition: PropertyManager.hh:160
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > makeTemporaryProperty(PolyConnectivity &mesh)
Creates a new property whose lifetime is limited to the current scope.
Definition: PropertyManager.hh:714
PROPTYPE::reference operator[](Handle handle)
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:455
bool hasProperty(const PolyConnectivity &mesh, const char *propname)
Tests whether a property with the given element type, value type, and name is present on the given me...
Definition: PropertyManager.hh:742
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager2 &dst_propmanager, HandleTypeIterator2 dst_begin, HandleTypeIterator2 dst_end) const
Conveniently transfer the values managed by one property manager onto the values managed by a differe...
Definition: PropertyManager.hh:549
PropertyManager< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(MeshT &mesh)
Returns a convenience wrapper around the points property of a mesh.
Definition: PropertyManager.hh:921
PROPTYPE::const_reference & operator*() const
Access the value of the encapsulated mesh property.
Definition: PropertyManager.hh:444
void set_persistent(bool _persistence=true)
Mark whether this property should be stored when mesh is written to a file.
Definition: PropertyManager.hh:602
PropertyManager(const PolyConnectivity &mesh)
Constructor.
Definition: PropertyManager.hh:210
PropertyManager(const Value &initial_value, const PolyConnectivity &mesh)
Constructor.
Definition: PropertyManager.hh:222
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getProperty(PolyConnectivity &mesh, const char *propname)
Obtains a handle to a named property.
Definition: PropertyManager.hh:776
PropertyManager clone()
Create property manager referring to a copy of the current property.
Definition: PropertyManager.hh:264
PropertyManager(PolyConnectivity &mesh, PROPTYPE property_handle)
Constructor.
Definition: PropertyManager.hh:235
PROPTYPE::reference operator()(const Handle &handle=Handle())
Enables convenient access to the encapsulated property.
Definition: PropertyManager.hh:477
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getOrMakeProperty(PolyConnectivity &mesh, const char *propname)
Obtains a handle to a named property if it exists or creates a new one otherwise.
Definition: PropertyManager.hh:817
PropertyManager(PolyConnectivity &mesh, const char *propname)
Constructor.
Definition: PropertyManager.hh:180
Definition: PropertyManager.hh:627

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .