Developer Documentation
Loading...
Searching...
No Matches
PropertyManager.hh
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2025, 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 <OpenMesh/Core/Mesh/PolyConnectivity.hh>
48#include <sstream>
49#include <stdexcept>
50#include <string>
51
52namespace OpenMesh {
53
75template<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
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
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(const 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 if (!exists)
394 pm.set_range(begin, end, init_value);
395 return std::move(pm);
396 }
397
407 template<typename PROP_VALUE, typename ITERATOR_RANGE>
408 static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
409 const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
410 return createIfNotExists(
411 mesh, propname, range.begin(), range.end(), init_value);
412 }
413
414
427 typename PROPTYPE::reference& operator*() {
428 return mesh().mproperty(prop_)[0];
429 }
430
443 typename PROPTYPE::const_reference& operator*() const {
444 return mesh().mproperty(prop_)[0];
445 }
446
454 inline typename PROPTYPE::reference operator[] (Handle handle) {
455 return mesh().property(prop_, handle);
456 }
457
465 inline typename PROPTYPE::const_reference operator[] (const Handle& handle) const {
466 return mesh().property(prop_, handle);
467 }
468
476 inline typename PROPTYPE::reference operator() (const Handle& handle = Handle()) {
477// return mesh().property(prop_, handle);
478 return Storage::access_property(mesh(), prop_, handle);
479 }
480
488 inline typename PROPTYPE::const_reference operator() (const Handle& handle = Handle()) const {
489// return mesh().property(prop_, handle);
490 return Storage::access_property_const(mesh(), prop_, handle);
491 }
492
517 template<typename HandleTypeIterator, typename PROP_VALUE>
518 void set_range(HandleTypeIterator begin, HandleTypeIterator end,
519 const PROP_VALUE &value) {
520 for (; begin != end; ++begin)
521 (*this)[*begin] = value;
522 }
523
524#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
525 template<typename HandleTypeIteratorRange, typename PROP_VALUE>
526 void set_range(const HandleTypeIteratorRange &range,
527 const PROP_VALUE &value) {
528 set_range(range.begin(), range.end(), value);
529 }
530#endif
531
546 template<typename HandleTypeIterator, typename PropertyManager2,
547 typename HandleTypeIterator2>
548 void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
549 PropertyManager2 &dst_propmanager,
550 HandleTypeIterator2 dst_begin, HandleTypeIterator2 dst_end) const {
551
552 for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
553 dst_propmanager[*dst_begin] = (*this)[*begin];
554 }
555 }
556
557 template<typename RangeType, typename PropertyManager2,
558 typename RangeType2>
559 void copy_to(const RangeType &range,
560 PropertyManager2 &dst_propmanager,
561 const RangeType2 &dst_range) const {
562 copy_to(range.begin(), range.end(), dst_propmanager,
563 dst_range.begin(), dst_range.end());
564 }
565
566
581 template<typename RangeType, typename RangeType2>
582 static void copy(const char *prop_name,
583 PolyConnectivity &src_mesh, const RangeType &src_range,
584 PolyConnectivity &dst_mesh, const RangeType2 &dst_range) {
585
587 DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
588
590 SrcPM src(src_mesh, prop_name, true);
591
592 src.copy_to(src_range, dst, dst_range);
593 }
594
601 void set_persistent(bool _persistence = true)
602 {
603 mesh().property(getRawProperty()).set_persistent(_persistence);
604 }
605
606 private:
607 void deleteProperty() {
608 if (!retain_ && prop_.is_valid())
609 mesh().remove_property(prop_);
610 }
611
612 PolyConnectivity& mesh() const
613 {
614 return const_cast<PolyConnectivity&>(mesh_);
615 }
616
617 private:
618 const PolyConnectivity& mesh_;
619 PROPTYPE prop_;
620 bool retain_;
621 std::string name_;
622};
623
624template <typename PropertyT>
626{
627public:
628 using Value = typename PropertyT::Value;
629 using value_type = typename PropertyT::value_type;
630 using Handle = typename PropertyT::Handle;
631
632 ConstPropertyViewer(const PolyConnectivity& mesh, const PropertyT& property_handle)
633 :
634 mesh_(mesh),
635 prop_(property_handle)
636 {}
637
638 inline const typename PropertyT::const_reference operator() (const Handle& handle)
639 {
640 return mesh_.property(prop_, handle);
641 }
642
643 inline const typename PropertyT::const_reference operator[] (const Handle& handle)
644 {
645 return mesh_.property(prop_, handle);
646 }
647
648private:
649 const PolyConnectivity& mesh_;
650 PropertyT prop_;
651};
652
680template<typename ElementT, typename T>
682OM_DEPRECATED("Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name")
683makeTemporaryProperty(PolyConnectivity &mesh, const char *propname) {
685}
686
711template<typename ElementT, typename T>
716
717
739template<typename ElementT, typename T>
740bool
741hasProperty(const PolyConnectivity &mesh, const char *propname) {
743 return mesh.get_property_handle(ph, propname);
744}
745
773template<typename ElementT, typename T>
775getProperty(PolyConnectivity &mesh, const char *propname) {
776 if (!hasProperty<ElementT, T>(mesh, propname))
777 {
778 std::ostringstream oss;
779 oss << "Requested property handle \"" << propname << "\" does not exist.";
780 throw std::runtime_error(oss.str());
781 }
783}
784
814template<typename ElementT, typename T>
816getOrMakeProperty(PolyConnectivity &mesh, const char *propname) {
817 return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>::createIfNotExists(mesh, propname);
818}
819
829template<typename PROPTYPE>
830OM_DEPRECATED("Use makeTemporaryProperty instead.")
831PropertyManager<PROPTYPE> makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
832{
833 return PropertyManager<PROPTYPE>(mesh, propname, false);
834}
835
848template<typename PROPTYPE, typename MeshT = int>
849OM_DEPRECATED("Use getProperty instead.")
850PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
851{
852 return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
853}
854
863template<typename PROPTYPE, typename MeshT = int>
864OM_DEPRECATED("Use getOrMakeProperty instead.")
865PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
866{
868}
869
881template<typename PROPTYPE,
882 typename ITERATOR_TYPE, typename PROP_VALUE>
883OM_DEPRECATED("Use getOrMakeProperty instead.")
884PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
885 PolyConnectivity &mesh, const char *propname,
886 const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
887 const PROP_VALUE &init_value) {
889 mesh, propname, begin, end, init_value);
890}
891
903template<typename PROPTYPE,
904 typename ITERATOR_RANGE, typename PROP_VALUE>
905OM_DEPRECATED("Use getOrMakeProperty instead.")
906PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
907 PolyConnectivity &mesh, const char *propname,
908 const ITERATOR_RANGE &range,
909 const PROP_VALUE &init_value) {
910 return makePropertyManagerFromExistingOrNew<PROPTYPE>(
911 mesh, propname, range.begin(), range.end(), init_value);
912}
913
914
918template<typename MeshT>
921 return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
922}
923
927template<typename MeshT>
931 return ConstPropertyViewer<PropType>(mesh, mesh.points_property_handle());
932}
933
934template <typename HandleT, typename T>
936
937template <typename T>
939
940template <typename T>
942
943template <typename T>
945
946template <typename T>
948
949template <typename T>
951
952
953} /* namespace OpenMesh */
954#endif /* PROPERTYMANAGER_HH_ */
void remove_property(VPropHandleT< T > &_ph)
PropertyT< T > & property(VPropHandleT< T > _ph)
bool get_property_handle(VPropHandleT< T > &_ph, const std::string &_name) const
Connectivity Class for polygonal meshes.
static void copy(const char *prop_name, PolyConnectivity &src_mesh, const RangeType &src_range, PolyConnectivity &dst_mesh, const RangeType2 &dst_range)
void set_range(HandleTypeIterator begin, HandleTypeIterator end, const PROP_VALUE &value)
PropertyManager(const Value &initial_value, PolyConnectivity &mesh, const char *propname)
ConstPropertyViewer< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(const MeshT &mesh)
PropertyManager(PolyConnectivity &mesh, const char *propname, bool existing)
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > makeTemporaryProperty(PolyConnectivity &mesh)
PROPTYPE::reference operator[](Handle handle)
bool hasProperty(const PolyConnectivity &mesh, const char *propname)
void copy_to(HandleTypeIterator begin, HandleTypeIterator end, PropertyManager2 &dst_propmanager, HandleTypeIterator2 dst_begin, HandleTypeIterator2 dst_end) const
PROPTYPE::reference & operator*()
PropertyManager< OpenMesh::VPropHandleT< typename MeshT::Point > > getPointsProperty(MeshT &mesh)
void set_persistent(bool _persistence=true)
PropertyManager(const PolyConnectivity &mesh)
PropertyManager(const Value &initial_value, const PolyConnectivity &mesh)
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getProperty(PolyConnectivity &mesh, const char *propname)
PropertyManager(PolyConnectivity &mesh, PROPTYPE property_handle)
PROPTYPE::reference operator()(const Handle &handle=Handle())
PropertyManager< typename HandleToPropHandle< ElementT, T >::type > getOrMakeProperty(PolyConnectivity &mesh, const char *propname)
PROPTYPE::const_reference & operator*() const
PropertyManager(PolyConnectivity &mesh, const char *propname)
Default property class for any type T.
Definition Property.hh:93
#define OM_DEPRECATED(msg)
define OM_SUPPRESS_DEPRECATED to suppress deprecated code warnings
Definition config.h:95
bool getMesh(int _identifier, PolyMesh *&_mesh)
Get the Poly Mesh which has the given identifier.