2015-04-28 11:54:17 +00:00
/* ========================================================================= *
2012-07-24 17:52:32 +00:00
* *
* OpenMesh *
2015-04-28 11:33:32 +00:00
* Copyright ( c ) 2001 - 2015 , RWTH - Aachen University *
2015-04-28 13:07:46 +00:00
* Department of Computer Graphics and Multimedia *
2015-04-28 11:33:32 +00:00
* All rights reserved . *
* www . openmesh . org *
2012-07-24 17:52:32 +00:00
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
2015-04-28 11:33:32 +00:00
* This file is part of OpenMesh . *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
2012-07-24 17:52:32 +00:00
* *
2015-04-28 11:33:32 +00:00
* Redistribution and use in source and binary forms , with or without *
* modification , are permitted provided that the following conditions *
* are met : *
* *
* 1. Redistributions of source code must retain the above copyright notice , *
* this list of conditions and the following disclaimer . *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice , this list of conditions and the following disclaimer in the *
* documentation and / or other materials provided with the distribution . *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission . *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED *
* TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , *
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR *
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING *
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE . *
2015-04-28 11:54:17 +00:00
* *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2012-07-24 17:52:32 +00:00
# ifndef PROPERTYMANAGER_HH_
# define PROPERTYMANAGER_HH_
2018-11-30 20:13:05 +01:00
# include <OpenMesh/Core/System/config.h>
# include <OpenMesh/Core/Utils/HandleToPropHandle.hh>
2019-10-31 14:09:08 +01:00
# include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
2012-07-24 17:52:32 +00:00
# include <sstream>
2013-05-23 09:36:41 +00:00
# include <stdexcept>
2013-08-07 08:03:39 +00:00
# include <string>
2012-07-24 17:52:32 +00:00
namespace OpenMesh {
/**
* This class is intended to manage the lifecycle of properties .
* It also defines convenience operators to access the encapsulated
* property ' s value .
*
2018-11-30 20:13:05 +01:00
* It is recommended to use the factory functions
* makeTemporaryProperty ( ) , getProperty ( ) , and getOrMakeProperty ( )
* to construct a PropertyManager , e . g .
2016-04-14 09:58:54 +02:00
*
2019-10-31 14:09:08 +01:00
* Note that the second template parameter is depcretated .
*
2016-04-14 09:58:54 +02:00
* \ code
2018-11-30 20:13:05 +01:00
* {
* TriMesh mesh ;
* auto visited = makeTemporaryProperty < VertexHandle , bool > ( mesh ) ;
2016-04-14 09:58:54 +02:00
*
2018-11-30 20:13:05 +01:00
* for ( auto vh : mesh . vertices ( ) ) {
* if ( ! visited [ vh ] ) {
* visitComponent ( mesh , vh , visited ) ;
* }
2016-04-14 09:58:54 +02:00
* }
2018-11-30 20:13:05 +01:00
* // The property is automatically removed at the end of the scope
2016-04-14 09:58:54 +02:00
* }
* \ endcode
2012-07-24 17:52:32 +00:00
*/
2019-10-31 14:09:08 +01:00
template < typename PROPTYPE , typename MeshT = int >
2012-07-24 17:52:32 +00:00
class PropertyManager {
2013-08-07 08:03:40 +00:00
public :
2019-10-31 15:27:34 +01:00
using Value = typename PROPTYPE : : Value ;
using value_type = typename PROPTYPE : : value_type ;
using Handle = typename PROPTYPE : : Handle ;
2019-10-31 17:56:37 +01:00
using Self = PropertyManager < PROPTYPE , MeshT > ;
2012-07-24 17:52:32 +00:00
private :
2019-10-31 17:56:37 +01:00
// Mesh properties (MPropHandleT<...>) are stored differently than the other properties.
// This class implements different behavior when copying or swapping data from one
// property manager to a another one.
template < typename PropertyManager2 , typename PropHandleT >
struct StorageT ;
// specialization for Mesh Properties
template < typename PropertyManager2 >
struct StorageT < PropertyManager2 , MPropHandleT < Value > > {
static void copy ( const PropertyManager < PROPTYPE , MeshT > & from , PropertyManager2 & to ) {
* to = * from ;
}
static void swap ( PropertyManager < PROPTYPE , MeshT > & from , PropertyManager2 & to ) {
std : : swap ( * to , * from ) ;
}
2019-11-05 15:30:05 +01:00
static const Value & access_property_const ( PolyConnectivity & mesh , const PROPTYPE & prop_handle , const Handle & ) {
return mesh . property ( prop_handle ) ;
}
static Value & access_property ( PolyConnectivity & mesh , const PROPTYPE & prop_handle , const Handle & ) {
return mesh . property ( prop_handle ) ;
}
2019-10-31 17:56:37 +01:00
} ;
2012-07-24 17:52:32 +00:00
2019-10-31 17:56:37 +01:00
// definition for other Mesh Properties
template < typename PropertyManager2 , typename PropHandleT >
struct StorageT {
static void copy ( const PropertyManager < PROPTYPE , MeshT > & from , PropertyManager2 & to ) {
from . copy_to ( from . mesh_ . template all_elements < Handle > ( ) , to , to . mesh_ . template all_elements < Handle > ( ) ) ;
}
static void swap ( PropertyManager < PROPTYPE , MeshT > & lhs , PropertyManager2 & rhs ) {
2019-11-05 15:30:05 +01:00
std : : swap ( lhs . mesh ( ) . property ( lhs . prop_ ) . data_vector ( ) , rhs . mesh ( ) . property ( rhs . prop_ ) . data_vector ( ) ) ;
2019-10-31 17:56:37 +01:00
// resize the property to the correct size
2019-11-05 15:30:05 +01:00
lhs . mesh ( ) . property ( lhs . prop_ ) . resize ( lhs . mesh ( ) . template n_elements < Handle > ( ) ) ;
rhs . mesh ( ) . property ( rhs . prop_ ) . resize ( rhs . mesh ( ) . template n_elements < Handle > ( ) ) ;
}
static const Value & access_property_const ( PolyConnectivity & mesh , const PROPTYPE & prop_handle , const Handle & handle ) {
return mesh . property ( prop_handle , handle ) ;
}
static Value & access_property ( PolyConnectivity & mesh , const PROPTYPE & prop_handle , const Handle & handle ) {
return mesh . property ( prop_handle , handle ) ;
2019-10-31 17:56:37 +01:00
}
} ;
using Storage = StorageT < Self , PROPTYPE > ;
2012-07-24 17:52:32 +00:00
public :
2019-10-31 15:27:34 +01:00
2012-07-24 17:52:32 +00:00
/**
2019-10-31 15:27:34 +01:00
* @ deprecated Use a constructor without \ p existing and check existance with hasProperty ( ) instead .
*
2012-07-24 17:52:32 +00:00
* Constructor .
*
* Throws an \ p std : : runtime_error if \ p existing is true and
* no property named \ p propname of the appropriate property type
* exists .
*
* @ param mesh The mesh on which to create the property .
* @ param propname The name of the property .
* @ param existing If false , a new property is created and its lifecycle is managed ( i . e .
* the property is deleted upon destruction of the PropertyManager instance ) . If true ,
* the instance merely acts as a convenience wrapper around an existing property with no
* lifecycle management whatsoever .
2016-04-14 09:58:54 +02:00
*
2019-10-31 15:27:34 +01:00
* @ see PropertyManager : : getOrMakeProperty , PropertyManager : : getProperty ,
* PropertyManager : : makeTemporaryProperty
2012-07-24 17:52:32 +00:00
*/
2019-11-05 09:40:48 +01:00
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
2019-10-31 15:27:34 +01:00
PropertyManager ( PolyConnectivity & mesh , const char * propname , bool existing ) : mesh_ ( mesh ) , retain_ ( existing ) , name_ ( propname ) {
2012-07-24 17:52:32 +00:00
if ( existing ) {
2019-11-05 15:30:05 +01:00
if ( ! PropertyManager : : mesh ( ) . get_property_handle ( prop_ , propname ) ) {
2012-07-24 17:52:32 +00:00
std : : ostringstream oss ;
oss < < " Requested property handle \" " < < propname < < " \" does not exist. " ;
throw std : : runtime_error ( oss . str ( ) ) ;
}
} else {
2019-11-05 15:30:05 +01:00
PropertyManager : : mesh ( ) . add_property ( prop_ , propname ) ;
2012-07-24 17:52:32 +00:00
}
}
2019-10-31 15:27:34 +01:00
/**
* Constructor .
*
* Asks for a property with name propname and creates one if none exists . Lifetime is not managed .
*
* @ param mesh The mesh on which to create the property .
* @ param propname The name of the property .
*/
PropertyManager ( PolyConnectivity & mesh , const char * propname ) : mesh_ ( mesh ) , retain_ ( true ) , name_ ( propname ) {
2019-11-05 15:30:05 +01:00
if ( ! PropertyManager : : mesh ( ) . get_property_handle ( prop_ , propname ) ) {
PropertyManager : : mesh ( ) . add_property ( prop_ , propname ) ;
2012-07-24 17:52:32 +00:00
}
}
2019-10-31 15:27:34 +01:00
/**
* Constructor .
*
* Asks for a property with name propname and creates one if none exists . Lifetime is not managed .
*
2019-11-05 18:12:37 +01:00
* @ param initial_value If the proeprty is newly created , it will be initialized with initial_value .
2019-11-05 09:40:48 +01:00
* If the property already existed , nothing is changes .
2019-10-31 15:27:34 +01:00
* @ param mesh The mesh on which to create the property .
* @ param propname The name of the property .
*/
2019-11-05 18:12:37 +01:00
PropertyManager ( const Value & initial_value , PolyConnectivity & mesh , const char * propname ) : mesh_ ( mesh ) , retain_ ( true ) , name_ ( propname ) {
2019-10-31 15:27:34 +01:00
if ( ! mesh_ . get_property_handle ( prop_ , propname ) ) {
2019-11-05 15:30:05 +01:00
PropertyManager : : mesh ( ) . add_property ( prop_ , propname ) ;
2019-11-05 18:12:37 +01:00
set_range ( mesh_ . all_elements < Handle > ( ) , initial_value ) ;
2019-10-31 15:27:34 +01:00
}
}
/**
* Constructor .
*
* Create an anonymous property . Lifetime is managed .
*
* @ param mesh The mesh on which to create the property .
*/
2019-11-05 15:30:05 +01:00
PropertyManager ( const PolyConnectivity & mesh ) : mesh_ ( mesh ) , retain_ ( false ) , name_ ( " " ) {
PropertyManager : : mesh ( ) . add_property ( prop_ , name_ ) ;
2019-10-31 15:27:34 +01:00
}
/**
* Constructor .
*
* Create an anonymous property . Lifetime is managed .
*
2019-11-05 18:12:37 +01:00
* @ param initial_value The property will be initialized with initial_value .
2019-10-31 15:27:34 +01:00
* @ param mesh The mesh on which to create the property .
*/
2019-11-05 18:16:57 +01:00
PropertyManager ( const Value & initial_value , const PolyConnectivity & mesh ) : mesh_ ( mesh ) , retain_ ( false ) , name_ ( " " ) {
2019-11-05 15:30:05 +01:00
PropertyManager : : mesh ( ) . add_property ( prop_ , name_ ) ;
2019-11-05 18:12:37 +01:00
set_range ( mesh_ . all_elements < Handle > ( ) , initial_value ) ;
2019-10-31 15:27:34 +01:00
}
/**
* Constructor .
*
* Create a wrapper around an existing property . Lifetime is not managed .
*
* @ param mesh The mesh on which to create the property .
2019-11-06 11:41:41 +01:00
* @ param property_handle Handle to an existing property that should be wrapped .
2019-10-31 15:27:34 +01:00
*/
PropertyManager ( PolyConnectivity & mesh , PROPTYPE property_handle ) : mesh_ ( mesh ) , prop_ ( property_handle ) , retain_ ( true ) , name_ ( ) {
}
PropertyManager ( ) = delete ;
PropertyManager ( const PropertyManager & rhs )
:
mesh_ ( rhs . mesh_ ) ,
prop_ ( ) ,
retain_ ( rhs . retain_ ) ,
name_ ( rhs . name_ )
{
if ( rhs . retain_ ) // named property -> create a property manager referring to the same
{
prop_ = rhs . prop_ ;
}
else // unnamed property -> create a property manager refering to a new property and copy the contents
{
2019-11-05 15:30:05 +01:00
PropertyManager : : mesh ( ) . add_property ( prop_ , name_ ) ;
2019-10-31 17:56:37 +01:00
Storage : : copy ( rhs , * this ) ;
2019-10-31 15:27:34 +01:00
}
}
PropertyManager & operator = ( const PropertyManager & rhs )
{
if ( & mesh_ = = & rhs . mesh_ & & prop_ = = rhs . prop_ )
; // nothing to do
else
2019-10-31 17:56:37 +01:00
Storage : : copy ( rhs , * this ) ;
2019-10-31 15:27:34 +01:00
return * this ;
2013-05-23 09:36:41 +00:00
}
2012-07-24 17:52:32 +00:00
~ PropertyManager ( ) {
deleteProperty ( ) ;
}
2012-09-17 06:28:07 +00:00
void swap ( PropertyManager & rhs ) {
2019-11-05 10:21:09 +01:00
// swap the data stored in the properties
Storage : : swap ( rhs , * this ) ;
2012-09-17 06:28:07 +00:00
}
2019-10-31 14:09:08 +01:00
static bool propertyExists ( PolyConnectivity & mesh , const char * propname ) {
2013-02-20 12:19:26 +00:00
PROPTYPE dummy ;
return mesh . get_property_handle ( dummy , propname ) ;
}
2019-10-31 14:09:08 +01:00
bool isValid ( ) const { return prop_ . is_valid ( ) ; }
2013-05-23 09:36:41 +00:00
operator bool ( ) const { return isValid ( ) ; }
const PROPTYPE & getRawProperty ( ) const { return prop_ ; }
2013-08-07 08:03:39 +00:00
const std : : string & getName ( ) const { return name_ ; }
2019-10-31 14:09:08 +01:00
/**
* Get the mesh corresponding to the property .
*
* If you use PropertyManager without second template parameter ( recommended )
* you need to specify the actual mesh type when using this function , e . g . :
* \ code
* {
* TriMesh mesh ;
* auto visited = VProp < bool > ( mesh ) ;
* TriMesh & mesh_ref = visited . getMesh < TriMesh > ( ) ;
* }
*
*/
template < typename MeshType >
2019-11-05 15:30:05 +01:00
const MeshType & getMesh ( ) const { return dynamic_cast < MeshType & > ( mesh_ ) ; }
2015-06-19 13:18:43 +00:00
2019-11-05 15:30:05 +01:00
const MeshT & getMesh ( ) const { return dynamic_cast < MeshT & > ( mesh_ ) ; }
2015-06-19 13:18:43 +00:00
2019-11-06 14:04:29 +01:00
/**
* @ deprecated This method no longer has any effect . Instead , named properties are always retained , while unnamed ones are not
*
* Tells the PropertyManager whether lifetime should be managed or not .
*/
OM_DEPRECATED ( " retain no longer has any effect. Instead, named properties are always retained, while unnamed ones are not. " )
void retain ( bool = true ) { }
2012-07-24 17:52:32 +00:00
/**
* Move constructor . Transfers ownership ( delete responsibility ) .
*/
2019-10-31 15:27:34 +01:00
PropertyManager ( PropertyManager & & rhs )
:
mesh_ ( rhs . mesh_ ) ,
prop_ ( rhs . prop_ ) ,
retain_ ( rhs . retain_ ) ,
name_ ( rhs . name_ )
{
if ( ! rhs . retain_ )
rhs . prop_ . invalidate ( ) ; // only invalidate unnamed properties
2012-07-24 17:52:32 +00:00
}
/**
* Move assignment . Transfers ownership ( delete responsibility ) .
*/
2019-10-31 15:27:34 +01:00
PropertyManager & operator = ( PropertyManager & & rhs )
{
if ( ( & mesh_ ! = & rhs . mesh_ ) | | ( prop_ ! = rhs . prop_ ) )
{
if ( rhs . retain_ )
{
// retained properties cannot be invalidated. Copy instead
2019-10-31 17:56:37 +01:00
Storage : : copy ( rhs , * this ) ;
2019-10-31 15:27:34 +01:00
}
else
{
2019-11-05 10:21:09 +01:00
// swap the data stored in the properties
2019-10-31 17:56:37 +01:00
Storage : : swap ( rhs , * this ) ;
2019-10-31 15:27:34 +01:00
// remove the property from rhs
2019-11-05 15:30:05 +01:00
rhs . mesh ( ) . remove_property ( rhs . prop_ ) ;
2019-10-31 15:27:34 +01:00
// invalidate prop_
rhs . prop_ . invalidate ( ) ;
}
2016-04-14 09:58:54 +02:00
}
2012-07-24 17:52:32 +00:00
return * this ;
}
2012-09-11 18:16:01 +00:00
/**
* Create a property manager for the supplied property and mesh .
* If the property doesn ' t exist , it is created . In any case ,
* lifecycle management is disabled .
2016-04-14 09:58:54 +02:00
*
* @ see makePropertyManagerFromExistingOrNew
2012-09-11 18:16:01 +00:00
*/
2019-10-31 14:09:08 +01:00
static PropertyManager createIfNotExists ( PolyConnectivity & mesh , const char * propname ) {
2019-10-31 15:27:34 +01:00
return PropertyManager ( mesh , propname ) ;
2012-09-11 18:16:01 +00:00
}
2012-09-17 06:28:07 +00:00
2016-09-12 16:58:03 +02:00
/**
* Like createIfNotExists ( ) with two parameters except , if the property
* doesn ' t exist , it is initialized with the supplied value over
* the supplied range after creation . If the property already exists ,
* this method has the exact same effect as the two parameter version .
* Lifecycle management is disabled in any case .
*
* @ see makePropertyManagerFromExistingOrNew
*/
template < typename PROP_VALUE , typename ITERATOR_TYPE >
2019-10-31 14:09:08 +01:00
static PropertyManager createIfNotExists ( PolyConnectivity & mesh , const char * propname ,
2016-09-12 16:58:03 +02:00
const ITERATOR_TYPE & begin , const ITERATOR_TYPE & end ,
const PROP_VALUE & init_value ) {
const bool exists = propertyExists ( mesh , propname ) ;
PropertyManager pm ( mesh , propname , exists ) ;
pm . retain ( ) ;
if ( ! exists )
pm . set_range ( begin , end , init_value ) ;
return std : : move ( pm ) ;
}
/**
* Like createIfNotExists ( ) with two parameters except , if the property
* doesn ' t exist , it is initialized with the supplied value over
* the supplied range after creation . If the property already exists ,
* this method has the exact same effect as the two parameter version .
* Lifecycle management is disabled in any case .
*
* @ see makePropertyManagerFromExistingOrNew
*/
template < typename PROP_VALUE , typename ITERATOR_RANGE >
2019-10-31 14:09:08 +01:00
static PropertyManager createIfNotExists ( PolyConnectivity & mesh , const char * propname ,
2016-09-12 16:58:03 +02:00
const ITERATOR_RANGE & range , const PROP_VALUE & init_value ) {
return createIfNotExists (
mesh , propname , range . begin ( ) , range . end ( ) , init_value ) ;
}
2014-02-13 09:25:46 +00:00
2014-06-26 11:38:13 +00:00
2012-07-24 17:52:32 +00:00
/**
2019-04-03 15:45:23 +02:00
* Access the value of the encapsulated mesh property .
*
* Example :
* @ code
* PolyMesh m ;
* auto description = getOrMakeProperty < void , std : : string > ( m , " description " ) ;
* * description = " This is a very nice mesh. " ;
* @ endcode
*
* @ note This method is only used for mesh properties .
2012-07-24 17:52:32 +00:00
*/
2019-04-03 15:45:23 +02:00
typename PROPTYPE : : reference & operator * ( ) {
2019-11-05 15:30:05 +01:00
return mesh ( ) . mproperty ( prop_ ) [ 0 ] ;
2012-07-24 17:52:32 +00:00
}
/**
2019-04-03 15:45:23 +02:00
* Access the value of the encapsulated mesh property .
*
* Example :
* @ code
* PolyMesh m ;
* auto description = getProperty < void , std : : string > ( m , " description " ) ;
* std : : cout < < * description < < std : : endl ;
* @ endcode
*
* @ note This method is only used for mesh properties .
2012-07-24 17:52:32 +00:00
*/
2019-04-03 15:45:23 +02:00
typename PROPTYPE : : const_reference & operator * ( ) const {
2019-11-05 15:30:05 +01:00
return mesh ( ) . mproperty ( prop_ ) [ 0 ] ;
2012-07-24 17:52:32 +00:00
}
/**
* Enables convenient access to the encapsulated property .
*
* For a usage example see this class ' documentation .
*
* @ param handle A handle of the appropriate handle type . ( I . e . \ p VertexHandle for \ p VPropHandleT , etc . )
*/
2019-11-05 15:30:05 +01:00
inline typename PROPTYPE : : reference operator [ ] ( Handle handle ) {
return mesh ( ) . property ( prop_ , handle ) ;
2012-07-24 17:52:32 +00:00
}
/**
* Enables convenient access to the encapsulated property .
*
* For a usage example see this class ' documentation .
*
* @ param handle A handle of the appropriate handle type . ( I . e . \ p VertexHandle for \ p VPropHandleT , etc . )
*/
2019-11-05 15:30:05 +01:00
inline typename PROPTYPE : : const_reference operator [ ] ( const Handle & handle ) const {
return mesh ( ) . property ( prop_ , handle ) ;
2012-07-24 17:52:32 +00:00
}
2019-09-27 14:45:20 +02:00
/**
* Enables convenient access to the encapsulated property .
*
* For a usage example see this class ' documentation .
*
* @ param handle A handle of the appropriate handle type . ( I . e . \ p VertexHandle for \ p VPropHandleT , etc . )
*/
2019-11-05 15:30:05 +01:00
inline typename PROPTYPE : : reference operator ( ) ( const Handle & handle = Handle ( ) ) {
// return mesh().property(prop_, handle);
return Storage : : access_property ( mesh ( ) , prop_ , handle ) ;
2019-09-27 14:45:20 +02:00
}
/**
* Enables convenient access to the encapsulated property .
*
* For a usage example see this class ' documentation .
*
* @ param handle A handle of the appropriate handle type . ( I . e . \ p VertexHandle for \ p VPropHandleT , etc . )
*/
2019-11-05 15:30:05 +01:00
inline typename PROPTYPE : : const_reference operator ( ) ( const Handle & handle = Handle ( ) ) const {
// return mesh().property(prop_, handle);
return Storage : : access_property_const ( mesh ( ) , prop_ , handle ) ;
2019-09-27 14:45:20 +02:00
}
2014-02-25 14:01:12 +00:00
/**
* Conveniently set the property for an entire range of values .
*
* Examples :
* \ code
* MeshT mesh ;
2019-10-31 14:09:08 +01:00
* PropertyManager < VPropHandleT < double > > distance (
2014-02-25 14:01:12 +00:00
* mesh , " distance.plugin-example.i8.informatik.rwth-aachen.de " ) ;
* distance . set_range (
* mesh . vertices_begin ( ) , mesh . vertices_end ( ) ,
* std : : numeric_limits < double > : : infinity ( ) ) ;
* \ endcode
* or
* \ code
* MeshT : : VertexHandle vh ;
* distance . set_range (
* mesh . vv_begin ( vh ) , mesh . vv_end ( vh ) ,
* std : : numeric_limits < double > : : infinity ( ) ) ;
* \ endcode
*
* @ param begin Start iterator . Needs to dereference to HandleType .
* @ param end End iterator . ( Exclusive . )
* @ param value The value the range will be set to .
*/
2015-05-12 09:55:33 +00:00
template < typename HandleTypeIterator , typename PROP_VALUE >
2014-02-25 14:01:12 +00:00
void set_range ( HandleTypeIterator begin , HandleTypeIterator end ,
2015-05-12 09:55:33 +00:00
const PROP_VALUE & value ) {
2014-02-25 14:01:12 +00:00
for ( ; begin ! = end ; + + begin )
( * this ) [ * begin ] = value ;
}
2017-04-25 15:50:30 +02:00
# if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
2016-09-12 16:57:33 +02:00
template < typename HandleTypeIteratorRange , typename PROP_VALUE >
2016-09-12 17:06:56 +02:00
void set_range ( const HandleTypeIteratorRange & range ,
2016-09-12 16:57:33 +02:00
const PROP_VALUE & value ) {
set_range ( range . begin ( ) , range . end ( ) , value ) ;
}
# endif
2014-10-08 08:49:06 +00:00
/**
* Conveniently transfer the values managed by one property manager
* onto the values managed by a different property manager .
*
* @ param begin Start iterator . Needs to dereference to HandleType . Will
* be used with this property manager .
* @ param end End iterator . ( Exclusive . ) Will be used with this property
* manager .
* @ param dst_propmanager The destination property manager .
* @ param dst_begin Start iterator . Needs to dereference to the
* HandleType of dst_propmanager . Will be used with dst_propmanager .
* @ param dst_end End iterator . ( Exclusive . )
* Will be used with dst_propmanager . Used to double check the bounds .
*/
template < typename HandleTypeIterator , typename PROPTYPE_2 ,
2019-10-31 14:09:08 +01:00
typename HandleTypeIterator_2 >
2014-10-08 08:49:06 +00:00
void copy_to ( HandleTypeIterator begin , HandleTypeIterator end ,
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE_2 > & dst_propmanager ,
2014-10-08 08:49:06 +00:00
HandleTypeIterator_2 dst_begin , HandleTypeIterator_2 dst_end ) const {
for ( ; begin ! = end & & dst_begin ! = dst_end ; + + begin , + + dst_begin ) {
2014-11-05 17:03:36 +00:00
dst_propmanager [ * dst_begin ] = ( * this ) [ * begin ] ;
2014-10-08 08:49:06 +00:00
}
}
template < typename RangeType , typename PROPTYPE_2 ,
2019-10-31 14:09:08 +01:00
typename RangeType_2 >
2014-11-05 17:03:36 +00:00
void copy_to ( const RangeType & range ,
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE_2 > & dst_propmanager ,
2014-11-05 17:03:36 +00:00
const RangeType_2 & dst_range ) const {
2014-10-08 08:49:06 +00:00
copy_to ( range . begin ( ) , range . end ( ) , dst_propmanager ,
dst_range . begin ( ) , dst_range . end ( ) ) ;
}
2019-10-31 17:56:37 +01:00
2014-11-05 17:03:36 +00:00
/**
* Copy the values of a property from a source range to
* a target range . The source range must not be smaller than the
* target range .
*
* @ param prop_name Name of the property to copy . Must exist on the
* source mesh . Will be created on the target mesh if it doesn ' t exist .
*
* @ param src_mesh Source mesh from which to copy .
* @ param src_range Source range which to copy . Must not be smaller than
* dst_range .
* @ param dst_mesh Destination mesh on which to copy .
* @ param dst_range Destination range .
*/
2019-10-31 14:09:08 +01:00
template < typename RangeType , typename RangeType_2 >
2014-11-05 17:03:36 +00:00
static void copy ( const char * prop_name ,
2019-10-31 14:09:08 +01:00
PolyConnectivity & src_mesh , const RangeType & src_range ,
PolyConnectivity & dst_mesh , const RangeType_2 & dst_range ) {
2014-11-05 17:03:36 +00:00
2019-10-31 14:09:08 +01:00
typedef OpenMesh : : PropertyManager < PROPTYPE > DstPM ;
2014-11-05 17:03:36 +00:00
DstPM dst ( DstPM : : createIfNotExists ( dst_mesh , prop_name ) ) ;
2019-10-31 14:09:08 +01:00
typedef OpenMesh : : PropertyManager < PROPTYPE > SrcPM ;
2014-11-05 17:03:36 +00:00
SrcPM src ( src_mesh , prop_name , true ) ;
src . copy_to ( src_range , dst , dst_range ) ;
}
2012-07-24 17:52:32 +00:00
private :
void deleteProperty ( ) {
2019-10-31 15:27:34 +01:00
if ( ! retain_ & & prop_ . is_valid ( ) )
2019-11-05 15:30:05 +01:00
mesh ( ) . remove_property ( prop_ ) ;
}
PolyConnectivity & mesh ( ) const
{
return const_cast < PolyConnectivity & > ( mesh_ ) ;
2012-07-24 17:52:32 +00:00
}
private :
2019-11-05 15:30:05 +01:00
const PolyConnectivity & mesh_ ;
2012-07-24 17:52:32 +00:00
PROPTYPE prop_ ;
bool retain_ ;
2013-08-07 08:03:39 +00:00
std : : string name_ ;
2012-07-24 17:52:32 +00:00
} ;
2019-11-05 15:30:05 +01:00
template < typename PropertyT >
class ConstPropertyViewer
{
public :
using Value = typename PropertyT : : Value ;
using value_type = typename PropertyT : : value_type ;
using Handle = typename PropertyT : : Handle ;
ConstPropertyViewer ( const PolyConnectivity & mesh , PropertyT property_handle )
:
mesh_ ( mesh ) ,
prop_ ( property_handle )
{ }
inline const typename PropertyT : : const_reference operator ( ) ( const Handle & handle )
{
return mesh_ . property ( prop_ , handle ) ;
}
inline const typename PropertyT : : const_reference operator [ ] ( const Handle & handle )
{
return mesh_ . property ( prop_ , handle ) ;
}
private :
const PolyConnectivity & mesh_ ;
PropertyT prop_ ;
} ;
2018-11-30 20:13:05 +01:00
/** @relates PropertyManager
2019-10-31 17:56:37 +01:00
*
* @ deprecated Temporary properties should not have a name .
2018-11-30 20:13:05 +01:00
*
* Creates a new property whose lifetime is limited to the current scope .
*
* Used for temporary properties . Shadows any existing properties of
* matching name and type .
*
* Example :
* @ code
* PolyMesh m ;
* {
* auto is_quad = makeTemporaryProperty < FaceHandle , bool > ( m ) ;
* for ( auto & fh : m . faces ( ) ) {
* is_quad [ fh ] = ( m . valence ( fh ) = = 4 ) ;
* }
* // The property is automatically removed from the mesh at the end of the scope.
* }
* @ endcode
*
* @ param mesh The mesh on which the property is created
* @ param propname ( optional ) The name of the created property
* @ tparam ElementT Element type of the created property , e . g . VertexHandle , HalfedgeHandle , etc .
* @ tparam T Value type of the created property , e . g . , \ p double , \ p int , etc .
* @ returns A PropertyManager handling the lifecycle of the property
*/
2019-10-31 14:09:08 +01:00
template < typename ElementT , typename T >
PropertyManager < typename HandleToPropHandle < ElementT , T > : : type >
2019-10-31 17:56:37 +01:00
OM_DEPRECATED ( " Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name " )
makeTemporaryProperty ( PolyConnectivity & mesh , const char * propname ) {
2019-10-31 14:09:08 +01:00
return PropertyManager < typename HandleToPropHandle < ElementT , T > : : type > ( mesh , propname , false ) ;
2018-11-30 20:13:05 +01:00
}
2019-10-31 17:56:37 +01:00
/** @relates PropertyManager
*
* Creates a new property whose lifetime is limited to the current scope .
*
* Used for temporary properties . Shadows any existing properties of
* matching name and type .
*
* Example :
* @ code
* PolyMesh m ;
* {
* auto is_quad = makeTemporaryProperty < FaceHandle , bool > ( m ) ;
* for ( auto & fh : m . faces ( ) ) {
* is_quad [ fh ] = ( m . valence ( fh ) = = 4 ) ;
* }
* // The property is automatically removed from the mesh at the end of the scope.
* }
* @ endcode
*
* @ param mesh The mesh on which the property is created
* @ tparam ElementT Element type of the created property , e . g . VertexHandle , HalfedgeHandle , etc .
* @ tparam T Value type of the created property , e . g . , \ p double , \ p int , etc .
* @ returns A PropertyManager handling the lifecycle of the property
*/
template < typename ElementT , typename T >
PropertyManager < typename HandleToPropHandle < ElementT , T > : : type >
makeTemporaryProperty ( PolyConnectivity & mesh ) {
return PropertyManager < typename HandleToPropHandle < ElementT , T > : : type > ( mesh ) ;
}
2019-10-31 15:27:34 +01:00
2019-10-31 17:56:37 +01:00
/** @relates PropertyManager
*
* Tests whether a property with the given element type , value type , and name is
* present on the given mesh .
*
* * Example :
* @ code
* PolyMesh m ;
* if ( hasProperty < FaceHandle , bool > ( m , " is_quad " ) ) {
* // We now know the property exists: getProperty won't throw.
* auto is_quad = getProperty < FaceHandle , bool > ( m , " is_quad " ) ;
* // Use is_quad here.
* }
* @ endcode
*
* @ param mesh The mesh in question
* @ param propname The property name of the expected property
* @ tparam ElementT Element type of the expected property , e . g . VertexHandle , HalfedgeHandle , etc .
* @ tparam T Value type of the expected property , e . g . , \ p double , \ p int , etc .
* @ tparam MeshT Type of the mesh . Can often be inferred from \ p mesh
*/
template < typename ElementT , typename T >
bool
hasProperty ( const PolyConnectivity & mesh , const char * propname ) {
typename HandleToPropHandle < ElementT , T > : : type ph ;
return mesh . get_property_handle ( ph , propname ) ;
2018-11-30 20:13:05 +01:00
}
/** @relates PropertyManager
*
* Obtains a handle to a named property .
*
* Example :
* @ code
* PolyMesh m ;
* {
* try {
* auto is_quad = getProperty < FaceHandle , bool > ( m , " is_quad " ) ;
* // Use is_quad here.
* }
* catch ( const std : : runtime_error & e ) {
* // There is no is_quad face property on the mesh.
* }
* }
* @ endcode
*
* @ pre Property with the name \ p propname of matching type exists .
* @ throws std : : runtime_error if no property with the name \ p propname of
* matching type exists .
* @ param mesh The mesh on which the property is created
* @ param propname The name of the created property
* @ tparam ElementT Element type of the created property , e . g . VertexHandle , HalfedgeHandle , etc .
* @ tparam T Value type of the created property , e . g . , \ p double , \ p int , etc .
* @ returns A PropertyManager wrapping the property
*/
2019-10-31 14:09:08 +01:00
template < typename ElementT , typename T >
PropertyManager < typename HandleToPropHandle < ElementT , T > : : type >
getProperty ( PolyConnectivity & mesh , const char * propname ) {
2019-10-31 17:56:37 +01:00
if ( ! hasProperty < ElementT , T > ( mesh , propname ) )
{
std : : ostringstream oss ;
oss < < " Requested property handle \" " < < propname < < " \" does not exist. " ;
throw std : : runtime_error ( oss . str ( ) ) ;
}
return PropertyManager < typename HandleToPropHandle < ElementT , T > : : type > ( mesh , propname ) ;
2018-11-30 20:13:05 +01:00
}
/** @relates PropertyManager
*
* Obtains a handle to a named property if it exists or creates a new one otherwise .
*
* Used for creating or accessing permanent properties .
*
* Example :
* @ code
* PolyMesh m ;
* {
* auto is_quad = getOrMakeProperty < FaceHandle , bool > ( m , " is_quad " ) ;
* for ( auto & fh : m . faces ( ) ) {
* is_quad [ fh ] = ( m . valence ( fh ) = = 4 ) ;
* }
* // The property remains on the mesh after the end of the scope.
* }
* {
* // Retrieve the property from the previous scope.
* auto is_quad = getOrMakeProperty < FaceHandle , bool > ( m , " is_quad " ) ;
* // Use is_quad here.
* }
* @ endcode
*
* @ param mesh The mesh on which the property is created
* @ param propname The name of the created property
* @ tparam ElementT Element type of the created property , e . g . VertexHandle , HalfedgeHandle , etc .
* @ tparam T Value type of the created property , e . g . , \ p double , \ p int , etc .
* @ returns A PropertyManager wrapping the property
*/
2019-10-31 14:09:08 +01:00
template < typename ElementT , typename T >
PropertyManager < typename HandleToPropHandle < ElementT , T > : : type >
getOrMakeProperty ( PolyConnectivity & mesh , const char * propname ) {
return PropertyManager < typename HandleToPropHandle < ElementT , T > : : type > : : createIfNotExists ( mesh , propname ) ;
2019-04-03 15:45:44 +02:00
}
2018-11-30 20:13:05 +01:00
/** @relates PropertyManager
* @ deprecated Use makeTemporaryProperty ( ) instead .
*
2016-04-14 09:58:54 +02:00
* Creates a new property whose lifecycle is managed by the returned
* PropertyManager .
*
2018-11-30 20:13:05 +01:00
* Intended for temporary properties . Shadows any existing properties of
2016-04-14 09:58:54 +02:00
* matching name and type .
*/
2019-10-31 14:09:08 +01:00
template < typename PROPTYPE >
2018-11-30 20:13:05 +01:00
OM_DEPRECATED ( " Use makeTemporaryProperty instead. " )
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE > makePropertyManagerFromNew ( PolyConnectivity & mesh , const char * propname )
2018-11-30 20:13:05 +01:00
{
2019-10-31 14:09:08 +01:00
return PropertyManager < PROPTYPE > ( mesh , propname , false ) ;
2016-04-14 09:58:54 +02:00
}
2016-05-23 15:04:28 +02:00
/** \relates PropertyManager
2018-11-30 20:13:05 +01:00
* @ deprecated Use getProperty ( ) instead .
*
2016-04-14 09:58:54 +02:00
* Creates a non - owning wrapper for an existing mesh property ( no lifecycle
* management ) .
*
* Intended for convenient access .
*
* @ pre Property with the name \ p propname of matching type exists .
* @ throws std : : runtime_error if no property with the name \ p propname of
* matching type exists .
*/
2019-10-31 14:09:08 +01:00
template < typename PROPTYPE >
2018-11-30 20:13:05 +01:00
OM_DEPRECATED ( " Use getProperty instead. " )
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE > makePropertyManagerFromExisting ( PolyConnectivity & mesh , const char * propname )
2018-11-30 20:13:05 +01:00
{
2019-10-31 14:09:08 +01:00
return PropertyManager < PROPTYPE > ( mesh , propname , true ) ;
2016-04-14 09:58:54 +02:00
}
2018-11-30 20:13:05 +01:00
/** @relates PropertyManager
* @ deprecated Use getOrMakeProperty ( ) instead .
*
2016-04-14 09:58:54 +02:00
* Creates a non - owning wrapper for a mesh property ( no lifecycle management ) .
* If the given property does not exist , it is created .
*
* Intended for creating or accessing persistent properties .
*/
2019-10-31 14:09:08 +01:00
template < typename PROPTYPE >
2018-11-30 20:13:05 +01:00
OM_DEPRECATED ( " Use getOrMakeProperty instead. " )
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE > makePropertyManagerFromExistingOrNew ( PolyConnectivity & mesh , const char * propname )
2018-11-30 20:13:05 +01:00
{
2019-10-31 14:09:08 +01:00
return PropertyManager < PROPTYPE > : : createIfNotExists ( mesh , propname ) ;
2016-04-14 09:58:54 +02:00
}
2018-11-30 20:13:05 +01:00
/** @relates PropertyManager
2016-09-12 16:58:03 +02:00
* Like the two parameter version of makePropertyManagerFromExistingOrNew ( )
* except it initializes the property with the specified value over the
* specified range if it needs to be created . If the property already exists ,
* this function has the exact same effect as the two parameter version .
*
* Creates a non - owning wrapper for a mesh property ( no lifecycle management ) .
* If the given property does not exist , it is created .
*
* Intended for creating or accessing persistent properties .
*/
2019-10-31 15:27:34 +01:00
template < typename PROPTYPE ,
2016-09-12 16:58:03 +02:00
typename ITERATOR_TYPE , typename PROP_VALUE >
2019-04-03 15:44:17 +02:00
OM_DEPRECATED ( " Use getOrMakeProperty instead. " )
2019-10-31 15:27:34 +01:00
PropertyManager < PROPTYPE > makePropertyManagerFromExistingOrNew (
PolyConnectivity & mesh , const char * propname ,
2016-09-12 16:58:03 +02:00
const ITERATOR_TYPE & begin , const ITERATOR_TYPE & end ,
const PROP_VALUE & init_value ) {
2019-10-31 15:27:34 +01:00
return PropertyManager < PROPTYPE > : : createIfNotExists (
2016-09-12 16:58:03 +02:00
mesh , propname , begin , end , init_value ) ;
}
2018-11-30 20:13:05 +01:00
/** @relates PropertyManager
2016-09-12 16:58:03 +02:00
* Like the two parameter version of makePropertyManagerFromExistingOrNew ( )
* except it initializes the property with the specified value over the
* specified range if it needs to be created . If the property already exists ,
* this function has the exact same effect as the two parameter version .
*
* Creates a non - owning wrapper for a mesh property ( no lifecycle management ) .
* If the given property does not exist , it is created .
*
* Intended for creating or accessing persistent properties .
*/
2019-10-31 14:09:08 +01:00
template < typename PROPTYPE ,
2016-09-12 16:58:03 +02:00
typename ITERATOR_RANGE , typename PROP_VALUE >
2019-04-03 15:44:17 +02:00
OM_DEPRECATED ( " Use getOrMakeProperty instead. " )
2019-10-31 14:09:08 +01:00
PropertyManager < PROPTYPE > makePropertyManagerFromExistingOrNew (
PolyConnectivity & mesh , const char * propname ,
2016-09-12 16:58:03 +02:00
const ITERATOR_RANGE & range ,
const PROP_VALUE & init_value ) {
2019-10-31 14:09:08 +01:00
return makePropertyManagerFromExistingOrNew < PROPTYPE > (
2016-09-12 16:58:03 +02:00
mesh , propname , range . begin ( ) , range . end ( ) , init_value ) ;
}
2019-10-31 15:27:34 +01:00
/** @relates PropertyManager
* Returns a convenience wrapper around the points property of a mesh .
*/
template < typename MeshT >
PropertyManager < OpenMesh : : VPropHandleT < typename MeshT : : Point > >
getPointsProperty ( MeshT & mesh ) {
return PropertyManager < OpenMesh : : VPropHandleT < typename MeshT : : Point > > ( mesh , mesh . points_property_handle ( ) ) ;
}
2019-11-05 15:30:05 +01:00
/** @relates PropertyManager
* Returns a convenience wrapper around the points property of a mesh that only allows const access .
*/
template < typename MeshT >
ConstPropertyViewer < OpenMesh : : VPropHandleT < typename MeshT : : Point > >
getPointsProperty ( const MeshT & mesh ) {
using PropType = OpenMesh : : VPropHandleT < typename MeshT : : Point > ;
return ConstPropertyViewer < PropType > ( mesh , mesh . points_property_handle ( ) ) ;
}
2019-10-31 17:56:37 +01:00
template < typename HandleT , typename T >
using Prop = PropertyManager < typename PropHandle < HandleT > : : template type < T > > ;
2019-10-31 15:27:34 +01:00
template < typename T >
using VProp = PropertyManager < OpenMesh : : VPropHandleT < T > > ;
template < typename T >
using HProp = PropertyManager < OpenMesh : : HPropHandleT < T > > ;
template < typename T >
using EProp = PropertyManager < OpenMesh : : EPropHandleT < T > > ;
template < typename T >
using FProp = PropertyManager < OpenMesh : : FPropHandleT < T > > ;
2019-10-31 17:56:37 +01:00
template < typename T >
using MProp = PropertyManager < OpenMesh : : MPropHandleT < T > > ;
2019-10-31 15:27:34 +01:00
2012-07-24 17:52:32 +00:00
} /* namespace OpenMesh */
# endif /* PROPERTYMANAGER_HH_ */