Merge branch 'CustomProperties' into 'master'
Automatic loading of properties stored in files without having to manually create the property before reading. See merge request OpenMesh/OpenMesh!302
This commit is contained in:
@@ -44,7 +44,10 @@ else ()
|
||||
vci_add_library (OpenMeshCore SHAREDANDSTATIC ${sources} ${headers})
|
||||
set_target_properties (OpenMeshCore PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} )
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(OpenMeshCore PUBLIC /bigobj)
|
||||
endif ()
|
||||
|
||||
# Add core as dependency before fixbundle
|
||||
|
||||
@@ -278,7 +278,6 @@ namespace OMFormat {
|
||||
}; // Chunk
|
||||
|
||||
// ------------------------------------------------------------ Helper
|
||||
|
||||
// -------------------- get size information
|
||||
|
||||
/// Return size of header in bytes.
|
||||
|
||||
@@ -91,31 +91,42 @@ namespace IO {
|
||||
/// It's used by the OM reader/writer modules.
|
||||
///
|
||||
/// The following specialization are provided:
|
||||
/// - Fundamental types except \c long \c double
|
||||
/// - Fundamental types except \c long
|
||||
/// - %OpenMesh vector types
|
||||
/// - %OpenMesh::StatusInfo
|
||||
/// - std::string (max. length 65535)
|
||||
/// - std::vector<T> (requires a specialization for T)
|
||||
///
|
||||
/// \todo Complete documentation of members
|
||||
template < typename T > struct binary
|
||||
template < typename T, typename = void > struct binary
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
/// Can we store T? Set this to true in your specialization.
|
||||
static const bool is_streamable = false;
|
||||
|
||||
/// What's the size of T? If it depends on the actual value (e.g. for vectors) return UnknownSize
|
||||
static size_t size_of(void) { return UnknownSize; }
|
||||
/// What't the size of a specific value of type T.
|
||||
static size_t size_of(const value_type&) { return UnknownSize; }
|
||||
|
||||
/// A string that identifies the type of T.
|
||||
static std::string type_identifier (void) { return "UnknownType"; }
|
||||
|
||||
/// Store a value of T and return the number of bytes written
|
||||
static
|
||||
size_t store( std::ostream& /* _os */,
|
||||
const value_type& /* _v */,
|
||||
bool /* _swap=false */)
|
||||
const value_type& /* _v */,
|
||||
bool /* _swap */ = false ,
|
||||
bool /* store_size */ = true ) // for vectors
|
||||
{ X; return 0; }
|
||||
|
||||
/// Restore a value of T and return the number of bytes read
|
||||
static
|
||||
size_t restore( std::istream& /* _is */,
|
||||
value_type& /* _v */,
|
||||
bool /* _swap=false */)
|
||||
value_type& /* _v */,
|
||||
bool /* _swap */ = false ,
|
||||
bool /* store_size */ = true ) // for vectors
|
||||
{ X; return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,11 @@
|
||||
#include <OpenMesh/Core/IO/SR_rbo.hh>
|
||||
#include <OpenMesh/Core/IO/SR_binary.hh>
|
||||
|
||||
|
||||
#include <OpenMesh/Core/Utils/typename.hh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
@@ -91,6 +96,7 @@ namespace IO {
|
||||
static const bool is_streamable = true; \
|
||||
static size_t size_of(const value_type&) { return sizeof(value_type); } \
|
||||
static size_t size_of(void) { return sizeof(value_type); } \
|
||||
static std::string type_identifier(void) { return #T; } \
|
||||
static size_t store( std::ostream& _os, const value_type& _val, \
|
||||
bool _swap=false) { \
|
||||
value_type tmp = _val; \
|
||||
@@ -120,12 +126,19 @@ SIMPLE_BINARY(char);
|
||||
SIMPLE_BINARY(int8_t);
|
||||
SIMPLE_BINARY(int16_t);
|
||||
SIMPLE_BINARY(int32_t);
|
||||
SIMPLE_BINARY(int64_t);
|
||||
//SIMPLE_BINARY(int64_t); // TODO: This does not work. Find out why.
|
||||
SIMPLE_BINARY(uint8_t);
|
||||
SIMPLE_BINARY(uint16_t);
|
||||
SIMPLE_BINARY(uint32_t);
|
||||
SIMPLE_BINARY(uint64_t);
|
||||
|
||||
//handles
|
||||
SIMPLE_BINARY(FaceHandle);
|
||||
SIMPLE_BINARY(EdgeHandle);
|
||||
SIMPLE_BINARY(HalfedgeHandle);
|
||||
SIMPLE_BINARY(VertexHandle);
|
||||
SIMPLE_BINARY(MeshHandle);
|
||||
|
||||
#undef SIMPLE_BINARY
|
||||
|
||||
// For unsigned long which is of size 64 bit on 64 bit
|
||||
@@ -142,6 +155,7 @@ SIMPLE_BINARY(uint64_t);
|
||||
static const bool is_streamable = true; \
|
||||
static size_t size_of(const value_type&) { return sizeof(value_type); } \
|
||||
static size_t size_of(void) { return sizeof(value_type); } \
|
||||
static std::string type_identifier(void) { return #T; } \
|
||||
static size_t store( std::ostream& _os, const value_type& _val, \
|
||||
bool _swap=false) { \
|
||||
value_type tmp = _val; \
|
||||
@@ -172,12 +186,14 @@ SIMPLE_BINARY(unsigned long);
|
||||
static const bool is_streamable = true; \
|
||||
static size_t size_of(void) { return sizeof(value_type); } \
|
||||
static size_t size_of(const value_type&) { return size_of(); } \
|
||||
static std::string type_identifier(void) { return #T; } \
|
||||
static size_t store( std::ostream& _os, const value_type& _val, \
|
||||
bool _swap=false) { \
|
||||
bool _swap=false) { \
|
||||
value_type tmp = _val; \
|
||||
size_t i, b = size_of(_val), N = value_type::size_; \
|
||||
if (_swap) for (i=0; i<N; ++i) \
|
||||
reverse_byte_order( tmp[i] ); \
|
||||
if (_swap) \
|
||||
for (i=0; i<N; ++i) \
|
||||
reverse_byte_order( tmp[i] ); \
|
||||
_os.write( (const char*)&tmp[0], b ); \
|
||||
return _os.good() ? b : 0; \
|
||||
} \
|
||||
@@ -207,6 +223,7 @@ VECTORTS_BINARY( 1 )
|
||||
VECTORTS_BINARY( 2 )
|
||||
VECTORTS_BINARY( 3 )
|
||||
VECTORTS_BINARY( 4 )
|
||||
VECTORTS_BINARY( 5 )
|
||||
VECTORTS_BINARY( 6 )
|
||||
|
||||
#undef VECTORTS_BINARY
|
||||
@@ -221,7 +238,7 @@ template <> struct binary< std::string > {
|
||||
static size_t size_of() { return UnknownSize; }
|
||||
static size_t size_of(const value_type &_v)
|
||||
{ return sizeof(length_t) + _v.size(); }
|
||||
|
||||
static std::string type_identifier(void) { return "std::string"; }
|
||||
static
|
||||
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
|
||||
{
|
||||
@@ -252,7 +269,6 @@ template <> struct binary< std::string > {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> struct binary<OpenMesh::Attributes::StatusInfo>
|
||||
{
|
||||
typedef OpenMesh::Attributes::StatusInfo value_type;
|
||||
@@ -263,6 +279,7 @@ template <> struct binary<OpenMesh::Attributes::StatusInfo>
|
||||
static size_t size_of() { return sizeof(status_t); }
|
||||
static size_t size_of(const value_type&) { return size_of(); }
|
||||
|
||||
static std::string type_identifier(void) { return "StatusInfo";}
|
||||
static size_t n_bytes(size_t _n_elem)
|
||||
{ return _n_elem*sizeof(status_t); }
|
||||
|
||||
@@ -307,8 +324,106 @@ struct FunctorRestore {
|
||||
bool swap_;
|
||||
};
|
||||
|
||||
#include <OpenMesh/Core/IO/SR_binary_vector_of_fundamentals.inl>
|
||||
#include <OpenMesh/Core/IO/SR_binary_vector_of_string.inl>
|
||||
template <typename T>
|
||||
struct binary< std::vector< T >, typename std::enable_if<std::is_default_constructible<T>::value>::type > {
|
||||
typedef std::vector< T > value_type;
|
||||
typedef typename value_type::value_type elem_type;
|
||||
|
||||
static const bool is_streamable = binary<T>::is_streamable;
|
||||
static size_t size_of(bool _store_size = true)
|
||||
{ return IO::UnknownSize; }
|
||||
|
||||
static size_t size_of(const value_type& _v, bool _store_size = true)
|
||||
{
|
||||
if(binary<T>::size_of() != IO::UnknownSize)
|
||||
{
|
||||
unsigned int N = _v.size();
|
||||
auto res = binary<T>::size_of()*_v.size() + (_store_size? sizeof(decltype(N)) : 0);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t size = 0;
|
||||
for(auto v : _v)
|
||||
size += binary<T>::size_of(v);
|
||||
if(_store_size)
|
||||
size += binary<unsigned int>::size_of();
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string type_identifier(void) { return "std::vector<" + binary<T>::type_identifier() + ">"; }
|
||||
static
|
||||
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false, bool _store_size = true) {
|
||||
size_t bytes=0;
|
||||
if(_store_size)
|
||||
{
|
||||
unsigned int N = _v.size();
|
||||
bytes += binary<unsigned int>::store( _os, N, _swap );
|
||||
}
|
||||
if (_swap)
|
||||
bytes += std::accumulate( _v.begin(), _v.end(), static_cast<size_t>(0),
|
||||
FunctorStore<elem_type>(_os,_swap) );
|
||||
else
|
||||
{
|
||||
auto elem_size = binary<elem_type>::size_of();
|
||||
if (elem_size != IO::UnknownSize && elem_size == sizeof(elem_type))
|
||||
{
|
||||
// size of all elements is known, equal, and densely packed in vector.
|
||||
// Just store vector data
|
||||
auto bytes_of_vec = size_of(_v, false);
|
||||
bytes += bytes_of_vec;
|
||||
if (_v.size() > 0)
|
||||
_os.write( reinterpret_cast<const char*>(&_v[0]), bytes_of_vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// store individual elements
|
||||
for (const auto& v : _v)
|
||||
bytes += binary<elem_type>::store(_os, v, _swap);
|
||||
}
|
||||
}
|
||||
return _os.good() ? bytes : 0;
|
||||
}
|
||||
|
||||
static size_t restore(std::istream& _is, value_type& _v, bool _swap=false, bool _restore_size = true) {
|
||||
|
||||
size_t bytes=0;
|
||||
|
||||
if(_restore_size)
|
||||
{
|
||||
unsigned int size_of_vec;
|
||||
bytes += binary<unsigned int>::restore(_is, size_of_vec, _swap);
|
||||
_v.resize(size_of_vec);
|
||||
}
|
||||
|
||||
if ( _swap)
|
||||
bytes += std::accumulate( _v.begin(), _v.end(), size_t(0),
|
||||
FunctorRestore<elem_type>(_is, _swap) );
|
||||
else
|
||||
{
|
||||
auto elem_size = binary<elem_type>::size_of();
|
||||
if (elem_size != IO::UnknownSize && elem_size == sizeof(elem_type))
|
||||
{
|
||||
// size of all elements is known, equal, and densely packed in vector.
|
||||
// Just restore vector data
|
||||
auto bytes_of_vec = size_of(_v, false);
|
||||
bytes += bytes_of_vec;
|
||||
if (_v.size() > 0)
|
||||
_is.read( reinterpret_cast<char*>(&_v[0]), bytes_of_vec );
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore individual elements
|
||||
for (auto& v : _v)
|
||||
bytes += binary<elem_type>::restore(_is, v, _swap);
|
||||
}
|
||||
}
|
||||
return _is.good() ? bytes : 0;
|
||||
}
|
||||
};
|
||||
|
||||
#include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -1,95 +1,103 @@
|
||||
|
||||
template <> struct binary< std::vector<bool> >
|
||||
{
|
||||
|
||||
typedef std::vector< bool > value_type;
|
||||
typedef value_type::value_type elem_type;
|
||||
|
||||
static const bool is_streamable = true;
|
||||
|
||||
static size_t size_of(void) { return UnknownSize; }
|
||||
static size_t size_of(const value_type& _v)
|
||||
static size_t size_of(bool _store_size = true) { return UnknownSize; }
|
||||
static size_t size_of(const value_type& _v, bool _store_size = true)
|
||||
{
|
||||
return _v.size() / 8 + ((_v.size() % 8)!=0);
|
||||
size_t size = _v.size() / 8 + ((_v.size() % 8)!=0);
|
||||
if(_store_size)
|
||||
size += binary<unsigned int>::size_of();
|
||||
return size;
|
||||
}
|
||||
|
||||
static std::string type_identifier(void) { return "std::vector<bool>"; }
|
||||
static
|
||||
size_t store( std::ostream& _ostr, const value_type& _v, bool )
|
||||
size_t store( std::ostream& _ostr, const value_type& _v, bool _swap, bool _store_size = true)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
|
||||
size_t N = _v.size() / 8;
|
||||
size_t R = _v.size() % 8;
|
||||
|
||||
size_t idx; // element index
|
||||
if(_store_size)
|
||||
{
|
||||
unsigned int size_N = _v.size();
|
||||
bytes += binary<unsigned int>::store( _ostr, size_N, _swap );
|
||||
}
|
||||
|
||||
size_t idx; // element index
|
||||
size_t bidx;
|
||||
unsigned char bits; // bitset
|
||||
|
||||
for (idx=0; idx < N; ++idx)
|
||||
for (bidx=idx=0; idx < N; ++idx, bidx+=8)
|
||||
{
|
||||
bits = static_cast<unsigned char>(_v[idx])
|
||||
| (static_cast<unsigned char>(_v[idx+1]) << 1)
|
||||
| (static_cast<unsigned char>(_v[idx+2]) << 2)
|
||||
| (static_cast<unsigned char>(_v[idx+3]) << 3)
|
||||
| (static_cast<unsigned char>(_v[idx+4]) << 4)
|
||||
| (static_cast<unsigned char>(_v[idx+5]) << 5)
|
||||
| (static_cast<unsigned char>(_v[idx+6]) << 6)
|
||||
| (static_cast<unsigned char>(_v[idx+7]) << 7);
|
||||
bits = static_cast<unsigned char>(_v[bidx])
|
||||
| (static_cast<unsigned char>(_v[bidx+1]) << 1)
|
||||
| (static_cast<unsigned char>(_v[bidx+2]) << 2)
|
||||
| (static_cast<unsigned char>(_v[bidx+3]) << 3)
|
||||
| (static_cast<unsigned char>(_v[bidx+4]) << 4)
|
||||
| (static_cast<unsigned char>(_v[bidx+5]) << 5)
|
||||
| (static_cast<unsigned char>(_v[bidx+6]) << 6)
|
||||
| (static_cast<unsigned char>(_v[bidx+7]) << 7);
|
||||
_ostr << bits;
|
||||
}
|
||||
bytes = N;
|
||||
bytes += N;
|
||||
|
||||
if (R)
|
||||
{
|
||||
bits = 0;
|
||||
switch(R)
|
||||
{
|
||||
case 7: bits |= (static_cast<unsigned char>(_v[idx+6]) << 6);
|
||||
case 6: bits |= (static_cast<unsigned char>(_v[idx+5]) << 5);
|
||||
case 5: bits |= (static_cast<unsigned char>(_v[idx+4]) << 4);
|
||||
case 4: bits |= (static_cast<unsigned char>(_v[idx+3]) << 3);
|
||||
case 3: bits |= (static_cast<unsigned char>(_v[idx+2]) << 2);
|
||||
case 2: bits |= (static_cast<unsigned char>(_v[idx+1]) << 1);
|
||||
case 1: bits |= static_cast<unsigned char>(_v[idx+0]);
|
||||
}
|
||||
for (idx=0; idx < R; ++idx)
|
||||
bits |= static_cast<unsigned char>(_v[bidx+idx]) << idx;
|
||||
_ostr << bits;
|
||||
++bytes;
|
||||
}
|
||||
|
||||
assert( bytes == size_of(_v) );
|
||||
assert( bytes == size_of(_v, _store_size) );
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static
|
||||
size_t restore( std::istream& _istr, value_type& _v, bool )
|
||||
size_t restore( std::istream& _istr, value_type& _v, bool _swap, bool _restore_size = true)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
|
||||
if(_restore_size)
|
||||
{
|
||||
unsigned int size_of_vec;
|
||||
bytes += binary<unsigned int>::restore(_istr, size_of_vec, _swap);
|
||||
_v.resize(size_of_vec);
|
||||
}
|
||||
|
||||
size_t N = _v.size() / 8;
|
||||
size_t R = _v.size() % 8;
|
||||
|
||||
size_t idx; // element index
|
||||
size_t bidx; //
|
||||
unsigned char bits; // bitset
|
||||
|
||||
for (idx=0; idx < N; ++idx)
|
||||
for (bidx=idx=0; idx < N; ++idx, bidx+=8)
|
||||
{
|
||||
_istr >> bits;
|
||||
_v[idx+0] = ((bits & 0x01)!=0);
|
||||
_v[idx+1] = ((bits & 0x02)!=0);
|
||||
_v[idx+2] = ((bits & 0x04)!=0);
|
||||
_v[idx+3] = ((bits & 0x08)!=0);
|
||||
_v[idx+4] = ((bits & 0x10)!=0);
|
||||
_v[idx+5] = ((bits & 0x20)!=0);
|
||||
_v[idx+6] = ((bits & 0x40)!=0);
|
||||
_v[idx+7] = ((bits & 0x80)!=0);
|
||||
_v[bidx+0] = (bits & 0x01) != 0;
|
||||
_v[bidx+1] = (bits & 0x02) != 0;
|
||||
_v[bidx+2] = (bits & 0x04) != 0;
|
||||
_v[bidx+3] = (bits & 0x08) != 0;
|
||||
_v[bidx+4] = (bits & 0x10) != 0;
|
||||
_v[bidx+5] = (bits & 0x20) != 0;
|
||||
_v[bidx+6] = (bits & 0x40) != 0;
|
||||
_v[bidx+7] = (bits & 0x80) != 0;
|
||||
}
|
||||
bytes = N;
|
||||
bytes += N;
|
||||
|
||||
if (R)
|
||||
{
|
||||
_istr >> bits;
|
||||
for(; idx < _v.size(); ++idx)
|
||||
_v[idx] = (bits & (1 << (idx%8)))!=0;
|
||||
for (idx=0; idx < R; ++idx)
|
||||
_v[bidx+idx] = (bits & (1<<idx)) != 0;
|
||||
++bytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
#define BINARY_VECTOR( T ) \
|
||||
template <> struct binary< std::vector< T > > { \
|
||||
typedef std::vector< T > value_type; \
|
||||
typedef value_type::value_type elem_type; \
|
||||
\
|
||||
static const bool is_streamable = true; \
|
||||
\
|
||||
static size_t size_of(void) \
|
||||
{ return IO::UnknownSize; } \
|
||||
\
|
||||
static size_t size_of(const value_type& _v) \
|
||||
{ return sizeof(elem_type)*_v.size(); } \
|
||||
\
|
||||
static \
|
||||
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false) { \
|
||||
size_t bytes=0; \
|
||||
\
|
||||
if (_swap) \
|
||||
bytes = std::accumulate( _v.begin(), _v.end(), bytes, \
|
||||
FunctorStore<elem_type>(_os,_swap) ); \
|
||||
else { \
|
||||
bytes = size_of(_v); \
|
||||
_os.write( reinterpret_cast<const char*>(&_v[0]), bytes ); \
|
||||
} \
|
||||
return _os.good() ? bytes : 0; \
|
||||
} \
|
||||
\
|
||||
static size_t restore(std::istream& _is, value_type& _v, bool _swap=false) { \
|
||||
size_t bytes=0; \
|
||||
\
|
||||
if ( _swap) \
|
||||
bytes = std::accumulate( _v.begin(), _v.end(), size_t(0), \
|
||||
FunctorRestore<elem_type>(_is, _swap) ); \
|
||||
else \
|
||||
{ \
|
||||
bytes = size_of(_v); \
|
||||
_is.read( reinterpret_cast<char*>(&_v[0]), bytes ); \
|
||||
} \
|
||||
return _is.good() ? bytes : 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
BINARY_VECTOR( short );
|
||||
BINARY_VECTOR( unsigned short );
|
||||
BINARY_VECTOR( int );
|
||||
BINARY_VECTOR( unsigned int );
|
||||
BINARY_VECTOR( long );
|
||||
BINARY_VECTOR( unsigned long );
|
||||
BINARY_VECTOR( float );
|
||||
BINARY_VECTOR( double );
|
||||
|
||||
#undef BINARY_VECTOR
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
template <> struct binary< std::vector< std::string > >
|
||||
{
|
||||
// struct binary interface
|
||||
|
||||
typedef std::vector< std::string > value_type;
|
||||
typedef value_type::value_type elem_type;
|
||||
|
||||
static const bool is_streamable = true;
|
||||
|
||||
// Helper
|
||||
|
||||
struct Sum
|
||||
{
|
||||
size_t operator() ( size_t _v1, const elem_type& _s2 )
|
||||
{ return _v1 + binary<elem_type>::size_of(_s2); }
|
||||
};
|
||||
|
||||
// struct binary interface
|
||||
|
||||
static size_t size_of(void) { return UnknownSize; }
|
||||
|
||||
static size_t size_of(const value_type& _v)
|
||||
{ return std::accumulate( _v.begin(), _v.end(), size_t(0), Sum() ); }
|
||||
|
||||
static
|
||||
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
|
||||
{
|
||||
return std::accumulate( _v.begin(), _v.end(), size_t(0),
|
||||
FunctorStore<elem_type>(_os, _swap) );
|
||||
}
|
||||
|
||||
static
|
||||
size_t restore(std::istream& _is, value_type& _v, bool _swap=false)
|
||||
{
|
||||
return std::accumulate( _v.begin(), _v.end(), size_t(0),
|
||||
FunctorRestore<elem_type>(_is, _swap) );
|
||||
}
|
||||
};
|
||||
@@ -89,18 +89,34 @@ template <typename T> inline
|
||||
size_t size_of( const T& _v )
|
||||
{ return binary< T >::size_of(_v); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t size_of( const std::vector<T> & _v, bool _store_size = true)
|
||||
{ return binary< std::vector<T> >::size_of(_v, _store_size); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t size_of(void)
|
||||
{ return binary< T >::size_of(); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t store( std::ostream& _os, const T& _v, bool _swap=false)
|
||||
size_t size_of(bool _store_size)
|
||||
{ return binary< std::vector<T> >::size_of(_store_size); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t store( std::ostream& _os, const T& _v, bool _swap =false)
|
||||
{ return binary< T >::store( _os, _v, _swap ); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t restore( std::istream& _is, T& _v, bool _swap=false)
|
||||
size_t store( std::ostream& _os, const std::vector<T>& _v, bool _swap=false, bool _store_size = true)
|
||||
{ return binary< std::vector<T> >::store( _os, _v, _swap, _store_size); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t restore( std::istream& _is, T& _v, bool _swap = false)
|
||||
{ return binary< T >::restore( _is, _v, _swap ); }
|
||||
|
||||
template <typename T> inline
|
||||
size_t restore( std::istream& _is, std::vector<T>& _v, bool _swap=false, bool _restore_size = true)
|
||||
{ return binary< std::vector<T> >::restore( _is, _v, _swap, _restore_size); }
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
@@ -152,6 +152,9 @@ public:
|
||||
// set incident face handle for given halfedge
|
||||
virtual void set_face(HalfedgeHandle _heh, FaceHandle _fh) = 0;
|
||||
|
||||
// request texture coordinate property
|
||||
virtual void request_face_texcoords2D() = 0;
|
||||
|
||||
// set vertex texture coordinate
|
||||
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord) = 0;
|
||||
|
||||
|
||||
@@ -285,9 +285,14 @@ public:
|
||||
mesh_.set_face_handle(_heh, _fh);
|
||||
}
|
||||
|
||||
virtual void request_face_texcoords2D() override
|
||||
{
|
||||
if(!mesh_.has_halfedge_texcoords2D())
|
||||
mesh_.request_halfedge_texcoords2D();
|
||||
}
|
||||
|
||||
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord) override
|
||||
{
|
||||
{
|
||||
if (mesh_.has_halfedge_texcoords2D())
|
||||
mesh_.set_texcoord2D(_heh, vector_cast<TexCoord2D>(_texcoord));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@
|
||||
#include <OpenMesh/Core/IO/OMFormat.hh>
|
||||
#include <OpenMesh/Core/IO/reader/OMReader.hh>
|
||||
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
|
||||
#include <OpenMesh/Core/Utils/typename.hh>
|
||||
|
||||
#include <OpenMesh/Core/Utils/PropertyCreator.hh>
|
||||
|
||||
//=== NAMESPACES ==============================================================
|
||||
|
||||
@@ -180,7 +182,6 @@ bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
while (!_is.eof()) {
|
||||
bytes_ += restore(_is, chunk_header_, swap);
|
||||
|
||||
@@ -400,10 +401,17 @@ bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi,
|
||||
}
|
||||
|
||||
case Chunk::Type_Custom:
|
||||
{
|
||||
if(header_.version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
Chunk::PropertyName property_type;
|
||||
bytes_ += restore(_is, property_type, _swap);
|
||||
add_generic_property(property_type, _bi);
|
||||
}
|
||||
|
||||
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
|
||||
|
||||
vidx = header_.n_vertices_;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -550,12 +558,20 @@ bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Op
|
||||
}
|
||||
|
||||
case Chunk::Type_Custom:
|
||||
{
|
||||
if(header_.version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
Chunk::PropertyName property_type;
|
||||
bytes_ += restore(_is, property_type, _swap);
|
||||
add_generic_property(property_type, _bi);
|
||||
}
|
||||
|
||||
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
|
||||
|
||||
fidx = header_.n_faces_;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: // skip unknown chunks
|
||||
{
|
||||
@@ -583,11 +599,18 @@ bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Op
|
||||
|
||||
switch (chunk_header_.type_) {
|
||||
case Chunk::Type_Custom:
|
||||
{
|
||||
if(header_.version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
Chunk::PropertyName property_type;
|
||||
bytes_ += restore(_is, property_type, _swap);
|
||||
add_generic_property(property_type, _bi);
|
||||
}
|
||||
|
||||
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case Chunk::Type_Status:
|
||||
{
|
||||
assert( OMFormat::dimensions(chunk_header_) == 1);
|
||||
@@ -626,10 +649,39 @@ bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi
|
||||
|
||||
switch (chunk_header_.type_) {
|
||||
case Chunk::Type_Custom:
|
||||
{
|
||||
if(header_.version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
Chunk::PropertyName property_type;
|
||||
bytes_ += restore(_is, property_type, _swap);
|
||||
add_generic_property(property_type, _bi);
|
||||
}
|
||||
|
||||
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
|
||||
break;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
case Chunk::Type_Texcoord:
|
||||
{
|
||||
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec2f::dim()));
|
||||
|
||||
//fileOptions_ += OpenMesh::IO::Options::FaceTexCoord;
|
||||
|
||||
if (_opt.face_has_texcoord())
|
||||
{
|
||||
_bi.request_face_texcoords2D();
|
||||
}
|
||||
OpenMesh::Vec2f v2f;
|
||||
for (size_t e_idx = 0; e_idx < header_.n_edges_*2; ++e_idx)
|
||||
{
|
||||
bytes_ += vector_restore(_is, v2f, _swap);
|
||||
if (_opt.face_has_texcoord())
|
||||
_bi.set_texcoord(HalfedgeHandle(int(e_idx)), v2f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
case Chunk::Type_Topology:
|
||||
{
|
||||
std::vector<HalfedgeHandle> next_halfedges;
|
||||
@@ -703,11 +755,18 @@ bool _OMReader_::read_binary_mesh_chunk(std::istream &_is, BaseImporter &_bi, Op
|
||||
|
||||
switch (chunk_header_.type_) {
|
||||
case Chunk::Type_Custom:
|
||||
{
|
||||
if(header_.version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
Chunk::PropertyName property_type;
|
||||
bytes_ += restore(_is, property_type, _swap);
|
||||
add_generic_property(property_type, _bi);
|
||||
}
|
||||
|
||||
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
// skip unknown chunk
|
||||
size_t chunk_size = OMFormat::chunk_data_size(header_, chunk_header_);
|
||||
@@ -747,14 +806,14 @@ size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _
|
||||
#endif
|
||||
|
||||
#if defined(OM_DEBUG)
|
||||
assert( block_size == b );
|
||||
assert( block_size == b);
|
||||
#endif
|
||||
|
||||
assert( block_size == _bp->size_of());
|
||||
|
||||
block_size = 0;
|
||||
} else {
|
||||
omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
|
||||
omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,6 +826,57 @@ size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------helper
|
||||
void _OMReader_:: add_generic_property(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const
|
||||
{
|
||||
// We want to support the old way of restoring properties, ie.
|
||||
// the user has manually created the corresponding property.
|
||||
// In that case the property does not need be registered.
|
||||
// However, the _bi.kerne()->_get_prop(property_name_) checks below
|
||||
// May return a property with the correct name but the wrong type.
|
||||
// For now we will have to live with that.
|
||||
|
||||
|
||||
PropertyCreationManager& manager = PropertyCreationManager::instance();
|
||||
switch (chunk_header_.entity_)
|
||||
{
|
||||
case OMFormat::Chunk::Entity_Vertex:
|
||||
{
|
||||
if (_bi.kernel()->_get_vprop(property_name_) == nullptr)
|
||||
manager.create_property<OpenMesh::VertexHandle>(*_bi.kernel(), _property_type, property_name_);
|
||||
break;
|
||||
}
|
||||
case OMFormat::Chunk::Entity_Face:
|
||||
{
|
||||
if (_bi.kernel()->_get_fprop(property_name_) == nullptr)
|
||||
manager.create_property<OpenMesh::FaceHandle>(*_bi.kernel(), _property_type, property_name_);
|
||||
break;
|
||||
}
|
||||
case OMFormat::Chunk::Entity_Edge:
|
||||
{
|
||||
if (_bi.kernel()->_get_eprop(property_name_) == nullptr)
|
||||
manager.create_property<OpenMesh::EdgeHandle>(*_bi.kernel(), _property_type, property_name_);
|
||||
break;
|
||||
}
|
||||
case OMFormat::Chunk::Entity_Halfedge:
|
||||
{
|
||||
if (_bi.kernel()->_get_hprop(property_name_) == nullptr)
|
||||
manager.create_property<OpenMesh::HalfedgeHandle>(*_bi.kernel(), _property_type, property_name_);
|
||||
break;
|
||||
}
|
||||
case OMFormat::Chunk::Entity_Mesh:
|
||||
{
|
||||
if (_bi.kernel()->_get_mprop(property_name_) == nullptr)
|
||||
manager.create_property<OpenMesh::MeshHandle>(*_bi.kernel(), _property_type, property_name_);
|
||||
break;
|
||||
}
|
||||
case OMFormat::Chunk::Entity_Sentinel:
|
||||
;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//=============================================================================
|
||||
|
||||
@@ -149,11 +149,14 @@ private:
|
||||
Options &_opt,
|
||||
bool _swap) const;
|
||||
|
||||
size_t restore_binary_custom_data( std::istream& _is,
|
||||
BaseProperty* _bp,
|
||||
size_t _n_elem,
|
||||
bool _swap) const;
|
||||
size_t restore_binary_custom_data(std::istream& _is,
|
||||
BaseProperty* _bp,
|
||||
size_t _n_elem,
|
||||
bool _swap) const;
|
||||
|
||||
//------------------helper
|
||||
private:
|
||||
void add_generic_property(OMFormat::Chunk::PropertyName& _property_type, BaseImporter& _bi) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ _OMWriter_& OMWriter() { return __OMWriterInstance; }
|
||||
|
||||
|
||||
const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
|
||||
const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,1);
|
||||
const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,2);
|
||||
|
||||
|
||||
_OMWriter_::
|
||||
@@ -303,7 +303,6 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
|
||||
chunk_header.dim_ = OMFormat::dim(t);
|
||||
chunk_header.bits_ = OMFormat::bits(t[0]);
|
||||
|
||||
// std::clog << chunk_header << std::endl;
|
||||
bytes += store(_os, chunk_header, swap);
|
||||
|
||||
for (i = 0, nV = header.n_vertices_; i < nV; ++i)
|
||||
@@ -337,6 +336,30 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------- write face texture coords
|
||||
if (_OMWriter_::version_ > OMFormat::mk_version(2,1) && _be.n_edges() && _opt.check(Options::FaceTexCoord))
|
||||
{
|
||||
|
||||
t = _be.texcoord(HalfedgeHandle(0));
|
||||
|
||||
chunk_header.name_ = false;
|
||||
chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
|
||||
chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
|
||||
chunk_header.signed_ = OMFormat::is_signed(t[0]);
|
||||
chunk_header.float_ = OMFormat::is_float(t[0]);
|
||||
chunk_header.dim_ = OMFormat::dim(t);
|
||||
chunk_header.bits_ = OMFormat::bits(t[0]);
|
||||
|
||||
bytes += store(_os, chunk_header, swap);
|
||||
|
||||
unsigned int nHE;
|
||||
for (i = 0, nHE = header.n_edges_*2; i < nHE; ++i)
|
||||
bytes += vector_store(_os, _be.texcoord(HalfedgeHandle(i)), swap);
|
||||
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
||||
// ---------- write vertex topology (outgoing halfedge)
|
||||
if (_be.n_vertices())
|
||||
{
|
||||
@@ -573,7 +596,7 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
|
||||
chunk_header.entity_ = OMFormat::Chunk::Entity_Sentinel;
|
||||
bytes += store(_os, chunk_header, swap);
|
||||
|
||||
// std::clog << "#bytes written: " << bytes << std::endl;
|
||||
omlog() << "#bytes written: " << bytes << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -581,7 +604,7 @@ bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
|
||||
const BaseProperty& _bp,
|
||||
BaseProperty& _bp,
|
||||
OMFormat::Chunk::Entity _entity,
|
||||
bool _swap) const
|
||||
{
|
||||
@@ -620,16 +643,22 @@ size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
|
||||
// 2. property name
|
||||
bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
|
||||
|
||||
// 3. block size
|
||||
bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
|
||||
//omlog() << " n_bytes = " << _bp.size_of() << std::endl;
|
||||
// 3. data type needed to add property automatically, supported by version 2.1 or later
|
||||
if(_OMWriter_::version_ > OMFormat::mk_version(2,1))
|
||||
{
|
||||
OMFormat::Chunk::PropertyName type = OMFormat::Chunk::PropertyName(_bp.get_storage_name());
|
||||
bytes += store(_os, type, _swap);
|
||||
}
|
||||
|
||||
// 4. data
|
||||
// 4. block size
|
||||
bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
|
||||
//omlog() << " block size = " << _bp.size_of() << std::endl;
|
||||
|
||||
// 5. data
|
||||
{
|
||||
size_t b;
|
||||
bytes += ( b=_bp.store( _os, _swap ) );
|
||||
//omlog() << " b = " << b << std::endl;
|
||||
assert( b == _bp.size_of() );
|
||||
assert(b == _bp.size_of());
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ protected:
|
||||
bool write_binary(std::ostream&, BaseExporter&, Options) const;
|
||||
|
||||
|
||||
size_t store_binary_custom_chunk( std::ostream&, const BaseProperty&,
|
||||
OMFormat::Chunk::Entity, bool) const;
|
||||
size_t store_binary_custom_chunk(std::ostream&, BaseProperty&,
|
||||
OMFormat::Chunk::Entity, bool) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -133,6 +133,9 @@ public: // I/O support
|
||||
/// persistency.
|
||||
virtual void set_persistent( bool _yn ) = 0;
|
||||
|
||||
///returns a unique string for the type of the elements
|
||||
virtual std::string get_storage_name() const = 0;
|
||||
|
||||
/// Number of elements in property
|
||||
virtual size_t n_elements() const = 0;
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
|
||||
|
||||
|
||||
#ifndef OPENMESH_PROPERTY_HH
|
||||
#define OPENMESH_PROPERTY_HH
|
||||
|
||||
//#ifndef OPENMESH_PROPERTY_HH
|
||||
//#define OPENMESH_PROPERTY_HH
|
||||
#pragma once
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include <OpenMesh/Core/IO/SR_store.hh>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
@@ -147,21 +150,23 @@ public:
|
||||
|
||||
virtual size_t store( std::ostream& _ostr, bool _swap ) const override
|
||||
{
|
||||
if ( IO::is_streamable<vector_type>() )
|
||||
return IO::store(_ostr, data_, _swap );
|
||||
if (IO::is_streamable<vector_type>() && element_size() != IO::UnknownSize)
|
||||
return IO::store(_ostr, data_, _swap, false); //does not need to store its length
|
||||
|
||||
size_t bytes = 0;
|
||||
for (size_t i=0; i<n_elements(); ++i)
|
||||
bytes += IO::store( _ostr, data_[i], _swap );
|
||||
bytes += IO::store( _ostr, data_[i], _swap);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
virtual size_t restore( std::istream& _istr, bool _swap ) override
|
||||
{
|
||||
if ( IO::is_streamable<vector_type>() )
|
||||
return IO::restore(_istr, data_, _swap );
|
||||
if ( IO::is_streamable<vector_type>() && element_size() != IO::UnknownSize)
|
||||
return IO::restore(_istr, data_, _swap, false); //does not need to restore its length
|
||||
|
||||
size_t bytes = 0;
|
||||
for (size_t i=0; i<n_elements(); ++i)
|
||||
bytes += IO::restore( _istr, data_[i], _swap );
|
||||
bytes += IO::restore( _istr, data_[i], _swap);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -207,6 +212,10 @@ public: // data access interface
|
||||
return p;
|
||||
}
|
||||
|
||||
std::string get_storage_name() const override
|
||||
{
|
||||
return OpenMesh::IO::binary<T>::type_identifier();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -371,6 +380,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
std::string get_storage_name() const override
|
||||
{
|
||||
return OpenMesh::IO::binary<bool>::type_identifier();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -381,88 +395,6 @@ private:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** Property specialization for std::string type.
|
||||
*/
|
||||
template <>
|
||||
class PropertyT<std::string> : public BaseProperty
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::string Value;
|
||||
typedef std::vector<std::string> vector_type;
|
||||
typedef std::string value_type;
|
||||
typedef vector_type::reference reference;
|
||||
typedef vector_type::const_reference const_reference;
|
||||
|
||||
public:
|
||||
|
||||
explicit PropertyT(const std::string& _name = "<unknown>", const std::string& _internal_type_name="" )
|
||||
: BaseProperty(_name, _internal_type_name)
|
||||
{ }
|
||||
|
||||
public: // inherited from BaseProperty
|
||||
|
||||
virtual void reserve(size_t _n) override { data_.reserve(_n); }
|
||||
virtual void resize(size_t _n) override { data_.resize(_n); }
|
||||
virtual void clear() override { data_.clear(); vector_type().swap(data_); }
|
||||
virtual void push_back() override { data_.push_back(std::string()); }
|
||||
virtual void swap(size_t _i0, size_t _i1) override {
|
||||
std::swap(data_[_i0], data_[_i1]);
|
||||
}
|
||||
virtual void copy(size_t _i0, size_t _i1) override
|
||||
{ data_[_i1] = data_[_i0]; }
|
||||
|
||||
public:
|
||||
|
||||
virtual void set_persistent( bool _yn ) override
|
||||
{ check_and_set_persistent<std::string>( _yn ); }
|
||||
|
||||
virtual size_t n_elements() const override { return data_.size(); }
|
||||
virtual size_t element_size() const override { return UnknownSize; }
|
||||
virtual size_t size_of() const override
|
||||
{ return IO::size_of( data_ ); }
|
||||
|
||||
virtual size_t size_of(size_t /* _n_elem */) const override
|
||||
{ return UnknownSize; }
|
||||
|
||||
/// Store self as one binary block. Max. length of a string is 65535 bytes.
|
||||
size_t store( std::ostream& _ostr, bool _swap ) const override
|
||||
{ return IO::store( _ostr, data_, _swap ); }
|
||||
|
||||
size_t restore( std::istream& _istr, bool _swap ) override
|
||||
{ return IO::restore( _istr, data_, _swap ); }
|
||||
|
||||
public:
|
||||
|
||||
const value_type* data() const {
|
||||
if( data_.empty() )
|
||||
return nullptr;
|
||||
|
||||
return (value_type*) &data_[0];
|
||||
}
|
||||
|
||||
/// Access the i'th element. No range check is performed!
|
||||
reference operator[](int _idx) {
|
||||
assert( size_t(_idx) < data_.size());
|
||||
return ((value_type*) &data_[0])[_idx];
|
||||
}
|
||||
|
||||
/// Const access the i'th element. No range check is performed!
|
||||
const_reference operator[](int _idx) const {
|
||||
assert( size_t(_idx) < data_.size());
|
||||
return ((value_type*) &data_[0])[_idx];
|
||||
}
|
||||
|
||||
PropertyT<value_type>* clone() const override {
|
||||
PropertyT<value_type>* p = new PropertyT<value_type>( *this );
|
||||
return p;
|
||||
}
|
||||
private:
|
||||
|
||||
vector_type data_;
|
||||
|
||||
};
|
||||
|
||||
/// Base property handle.
|
||||
template <class T>
|
||||
struct BasePropHandleT : public BaseHandle
|
||||
@@ -578,7 +510,13 @@ struct PropHandle<FaceHandle> {
|
||||
using type = FPropHandleT<T>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PropHandle<MeshHandle> {
|
||||
template <typename T>
|
||||
using type = MPropHandleT<T>;
|
||||
};
|
||||
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_PROPERTY_HH defined
|
||||
//#endif // OPENMESH_PROPERTY_HH defined
|
||||
//=============================================================================
|
||||
|
||||
153
src/OpenMesh/Core/Utils/PropertyCreator.cc
Normal file
153
src/OpenMesh/Core/Utils/PropertyCreator.cc
Normal file
@@ -0,0 +1,153 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2020, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
#include "PropertyCreator.hh"
|
||||
|
||||
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
#include <OpenMesh/Core/IO/SR_types.hh>
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
PropertyCreationManager& PropertyCreationManager::instance()
|
||||
{
|
||||
static PropertyCreationManager manager;
|
||||
return manager;
|
||||
}
|
||||
|
||||
bool PropertyCreator::can_you_create(const std::string& _type_name)
|
||||
{
|
||||
return _type_name == type_string();
|
||||
}
|
||||
|
||||
|
||||
} /* namespace OpenMesh */
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(FaceHandle)
|
||||
OM_REGISTER_PROPERTY_TYPE(EdgeHandle)
|
||||
OM_REGISTER_PROPERTY_TYPE(HalfedgeHandle)
|
||||
OM_REGISTER_PROPERTY_TYPE(VertexHandle)
|
||||
OM_REGISTER_PROPERTY_TYPE(MeshHandle)
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(bool)
|
||||
OM_REGISTER_PROPERTY_TYPE(float)
|
||||
OM_REGISTER_PROPERTY_TYPE(double)
|
||||
OM_REGISTER_PROPERTY_TYPE(long double)
|
||||
OM_REGISTER_PROPERTY_TYPE(char)
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::int8_t )
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::int16_t )
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::int32_t )
|
||||
//OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::int64_t )
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::uint8_t )
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::uint16_t)
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::uint32_t)
|
||||
OM_REGISTER_PROPERTY_TYPE(OpenMesh::IO::uint64_t)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::string)
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<bool>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<float>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<double>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<long double>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<char>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::int8_t >)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::int16_t >)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::int32_t >)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::uint8_t >)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::uint16_t>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::uint32_t>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<OpenMesh::IO::uint64_t>)
|
||||
OM_REGISTER_PROPERTY_TYPE(std::vector<std::string>)
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec1d);
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec2d);
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec3d);
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec4d);
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec5d);
|
||||
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6c);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6uc);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6s);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6us);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6i);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6ui);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6f);
|
||||
OM_REGISTER_PROPERTY_TYPE(Vec6d);
|
||||
242
src/OpenMesh/Core/Utils/PropertyCreator.hh
Normal file
242
src/OpenMesh/Core/Utils/PropertyCreator.hh
Normal file
@@ -0,0 +1,242 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2020, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/HandleToPropHandle.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <OpenMesh/Core/IO/SR_store.hh>
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
#define OM_CONCAT_IMPL(a, b) a##b
|
||||
#define OM_CONCAT(a, b) OM_CONCAT_IMPL(a, b)
|
||||
|
||||
/** \brief Base class for property creators
|
||||
*
|
||||
* A PropertyCreator can add a named property to a mesh.
|
||||
* The type of the property is specified in the classes derived from this class.
|
||||
*
|
||||
* */
|
||||
class OPENMESHDLLEXPORT PropertyCreator
|
||||
{
|
||||
public:
|
||||
|
||||
/// The string that corresponds to the type this property creator can create
|
||||
virtual std::string type_string() = 0;
|
||||
|
||||
virtual std::string type_id_string() = 0;
|
||||
|
||||
/// Returns true iff the given _type_name corresponds to the string the derived class can create a property for
|
||||
bool can_you_create(const std::string &_type_name);
|
||||
|
||||
/// Create a vertex property on _mesh with name _property_name
|
||||
virtual void create_vertex_property (BaseKernel& _mesh, const std::string& _property_name) = 0;
|
||||
|
||||
/// Create a halfedge property on _mesh with name _property_name
|
||||
virtual void create_halfedge_property(BaseKernel& _mesh, const std::string& _property_name) = 0;
|
||||
|
||||
/// Create an edge property on _mesh with name _property_name
|
||||
virtual void create_edge_property (BaseKernel& _mesh, const std::string& _property_name) = 0;
|
||||
|
||||
/// Create a face property on _mesh with name _property_name
|
||||
virtual void create_face_property (BaseKernel& _mesh, const std::string& _property_name) = 0;
|
||||
|
||||
/// Create a mesh property on _mesh with name _property_name
|
||||
virtual void create_mesh_property (BaseKernel& _mesh, const std::string& _property_name) = 0;
|
||||
|
||||
|
||||
/// Create a property for the element of type HandleT on _mesh with name _property_name
|
||||
template <typename HandleT>
|
||||
void create_property(BaseKernel& _mesh, const std::string& _property_name);
|
||||
|
||||
virtual ~PropertyCreator() {}
|
||||
|
||||
protected:
|
||||
PropertyCreator() {}
|
||||
|
||||
};
|
||||
|
||||
template <> inline void PropertyCreator::create_property<VertexHandle> (BaseKernel& _mesh, const std::string& _property_name) { create_vertex_property (_mesh, _property_name); }
|
||||
template <> inline void PropertyCreator::create_property<HalfedgeHandle>(BaseKernel& _mesh, const std::string& _property_name) { create_halfedge_property(_mesh, _property_name); }
|
||||
template <> inline void PropertyCreator::create_property<EdgeHandle> (BaseKernel& _mesh, const std::string& _property_name) { create_edge_property (_mesh, _property_name); }
|
||||
template <> inline void PropertyCreator::create_property<FaceHandle> (BaseKernel& _mesh, const std::string& _property_name) { create_face_property (_mesh, _property_name); }
|
||||
template <> inline void PropertyCreator::create_property<MeshHandle> (BaseKernel& _mesh, const std::string& _property_name) { create_mesh_property (_mesh, _property_name); }
|
||||
|
||||
/// Helper class that contains the implementation of the create_<HandleT>_property methods.
|
||||
/// Implementation is injected into PropertyCreatorT.
|
||||
template <typename PropertyCreatorT>
|
||||
class PropertyCreatorImpl : public PropertyCreator
|
||||
{
|
||||
public:
|
||||
std::string type_id_string() override { return get_type_name<typename PropertyCreatorT::type>(); }
|
||||
|
||||
template <typename HandleT, typename PropT>
|
||||
void create_prop(BaseKernel& _mesh, const std::string& _property_name)
|
||||
{
|
||||
using PHandle = typename PropHandle<HandleT>::template type<PropT>;
|
||||
PHandle prop;
|
||||
if (!_mesh.get_property_handle(prop, _property_name))
|
||||
_mesh.add_property(prop, _property_name);
|
||||
}
|
||||
|
||||
void create_vertex_property (BaseKernel& _mesh, const std::string& _property_name) override { create_prop<VertexHandle , typename PropertyCreatorT::type>(_mesh, _property_name); }
|
||||
void create_halfedge_property(BaseKernel& _mesh, const std::string& _property_name) override { create_prop<HalfedgeHandle, typename PropertyCreatorT::type>(_mesh, _property_name);}
|
||||
void create_edge_property (BaseKernel& _mesh, const std::string& _property_name) override { create_prop<EdgeHandle , typename PropertyCreatorT::type>(_mesh, _property_name);}
|
||||
void create_face_property (BaseKernel& _mesh, const std::string& _property_name) override { create_prop<FaceHandle , typename PropertyCreatorT::type>(_mesh, _property_name);}
|
||||
void create_mesh_property (BaseKernel& _mesh, const std::string& _property_name) override { create_prop<MeshHandle , typename PropertyCreatorT::type>(_mesh, _property_name);}
|
||||
|
||||
~PropertyCreatorImpl() override {}
|
||||
protected:
|
||||
PropertyCreatorImpl() {}
|
||||
};
|
||||
|
||||
/// Actual PropertyCreators specialize this class in order to add properties of type T
|
||||
namespace {
|
||||
template <typename T>
|
||||
class PropertyCreatorT : public PropertyCreatorImpl<PropertyCreatorT<T>>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
///used to register custom type, where typename.hh does provide a string for type recognition
|
||||
|
||||
#define OM_REGISTER_PROPERTY_TYPE(ClassName) \
|
||||
namespace OpenMesh { \
|
||||
namespace { /* ensure internal linkage of class */ \
|
||||
template <> \
|
||||
class PropertyCreatorT<ClassName> : public PropertyCreatorImpl<PropertyCreatorT<ClassName>> \
|
||||
{ \
|
||||
public: \
|
||||
using type = ClassName; \
|
||||
std::string type_string() override { return OpenMesh::IO::binary<type>::type_identifier(); } \
|
||||
\
|
||||
PropertyCreatorT() \
|
||||
{ \
|
||||
PropertyCreationManager::instance().register_property_creator(this); \
|
||||
} \
|
||||
~PropertyCreatorT() override {} \
|
||||
}; \
|
||||
} \
|
||||
/* static to ensure internal linkage of object */ \
|
||||
static PropertyCreatorT<ClassName> OM_CONCAT(property_creator_registration_object_, __LINE__); \
|
||||
}
|
||||
|
||||
/** \brief Class for adding properties based on strings
|
||||
*
|
||||
* The PropertyCreationManager holds all PropertyCreators and dispatches the property creation
|
||||
* to them if they are able to create a property for a given string.
|
||||
*
|
||||
* If you want to be able to store your custom properties into a file and automatically load
|
||||
* them without manually adding the property yourself you can register your type by calling the
|
||||
* OM_REGISTER_PROPERTY_TYPE(ClassName, TypeString)
|
||||
* */
|
||||
class OPENMESHDLLEXPORT PropertyCreationManager
|
||||
{
|
||||
public:
|
||||
|
||||
static PropertyCreationManager& instance();
|
||||
|
||||
template <typename HandleT>
|
||||
void create_property(BaseKernel& _mesh, const std::string& _type_name, const std::string& _property_name)
|
||||
{
|
||||
|
||||
auto can_create = [_type_name](OpenMesh::PropertyCreator* pc){
|
||||
return pc->can_you_create(_type_name);
|
||||
};
|
||||
|
||||
std::vector<OpenMesh::PropertyCreator*>::iterator pc_iter = std::find_if(property_creators_.begin(),
|
||||
property_creators_.end(), can_create);
|
||||
if (pc_iter != property_creators_.end())
|
||||
{
|
||||
const auto& pc = *pc_iter;
|
||||
pc->create_property<HandleT>(_mesh, _property_name);
|
||||
return;
|
||||
}
|
||||
|
||||
omerr() << "No property creator registered that can create a property of type " << _type_name << std::endl;
|
||||
omerr() << "You need to register your custom type using OM_REGISTER_PROPERTY_TYPE(ClassName) and declare the struct binary<ClassName>.\
|
||||
See documentation for more details." << std::endl;
|
||||
omerr() << "Adding property failed." << std::endl;
|
||||
}
|
||||
|
||||
void register_property_creator(PropertyCreator* _property_creator)
|
||||
{
|
||||
for (auto pc : property_creators_)
|
||||
if (pc->type_string() == _property_creator->type_string())
|
||||
{
|
||||
if (pc->type_id_string() != _property_creator->type_id_string())
|
||||
{
|
||||
omerr() << "And it looks like you are trying to add a different type with an already existing string identification." << std::endl;
|
||||
omerr() << "Type id of existing type is " << pc->type_id_string() << " trying to add for " << _property_creator->type_id_string() << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
property_creators_.push_back(_property_creator);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PropertyCreationManager() {}
|
||||
~PropertyCreationManager() {}
|
||||
|
||||
std::vector<PropertyCreator*> property_creators_;
|
||||
};
|
||||
|
||||
/** \brief Create a property with type corresponding to _type_name on _mesh with name _property_name
|
||||
*
|
||||
* For user defined types you need to register the type using OM_REGISTER_PROPERTY_TYPE(ClassName, TypeString)
|
||||
* */
|
||||
template <typename HandleT>
|
||||
void create_property_from_string(BaseKernel& _mesh, const std::string& _type_name, const std::string& _property_name)
|
||||
{
|
||||
PropertyCreationManager::instance().create_property<HandleT>(_mesh, _type_name, _property_name);
|
||||
}
|
||||
|
||||
} /* namespace OpenMesh */
|
||||
@@ -207,7 +207,7 @@ class PropertyManager {
|
||||
*
|
||||
* @param mesh The mesh on which to create the property.
|
||||
*/
|
||||
PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||
explicit PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||
PropertyManager::mesh().add_property(prop_, name_);
|
||||
}
|
||||
|
||||
@@ -630,7 +630,7 @@ public:
|
||||
using value_type = typename PropertyT::value_type;
|
||||
using Handle = typename PropertyT::Handle;
|
||||
|
||||
ConstPropertyViewer(const PolyConnectivity& mesh, PropertyT property_handle)
|
||||
ConstPropertyViewer(const PolyConnectivity& mesh, const PropertyT& property_handle)
|
||||
:
|
||||
mesh_(mesh),
|
||||
prop_(property_handle)
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
@@ -23,4 +26,4 @@ std::string get_type_name()
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}//namespace OpenMesh
|
||||
|
||||
Reference in New Issue
Block a user