allow adding temporary properties on const meshes
This commit is contained in:
@@ -101,6 +101,12 @@ class PropertyManager {
|
|||||||
static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
||||||
std::swap(*to, *from);
|
std::swap(*to, *from);
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// definition for other Mesh Properties
|
// definition for other Mesh Properties
|
||||||
@@ -110,10 +116,16 @@ class PropertyManager {
|
|||||||
from.copy_to(from.mesh_.template all_elements<Handle>(), to, to.mesh_.template all_elements<Handle>());
|
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) {
|
static void swap(PropertyManager<PROPTYPE, MeshT>& lhs, PropertyManager2& rhs) {
|
||||||
std::swap(lhs.mesh_.property(lhs.prop_).data_vector(), rhs.mesh_.property(rhs.prop_).data_vector());
|
std::swap(lhs.mesh().property(lhs.prop_).data_vector(), rhs.mesh().property(rhs.prop_).data_vector());
|
||||||
// resize the property to the correct size
|
// resize the property to the correct size
|
||||||
lhs.mesh_.property(lhs.prop_).resize(lhs.mesh_.template n_elements<Handle>());
|
lhs.mesh().property(lhs.prop_).resize(lhs.mesh().template n_elements<Handle>());
|
||||||
rhs.mesh_.property(rhs.prop_).resize(rhs.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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,13 +155,13 @@ class PropertyManager {
|
|||||||
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
|
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
|
||||||
PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
|
PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
||||||
throw std::runtime_error(oss.str());
|
throw std::runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mesh_.add_property(prop_, propname);
|
PropertyManager::mesh().add_property(prop_, propname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +174,8 @@ class PropertyManager {
|
|||||||
* @param propname The name of the property.
|
* @param propname The name of the property.
|
||||||
*/
|
*/
|
||||||
PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
||||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
if (!PropertyManager::mesh().get_property_handle(prop_, propname)) {
|
||||||
mesh_.add_property(prop_, propname);
|
PropertyManager::mesh().add_property(prop_, propname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +191,7 @@ class PropertyManager {
|
|||||||
*/
|
*/
|
||||||
PropertyManager(const Value& intial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
PropertyManager(const Value& intial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
||||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
if (!mesh_.get_property_handle(prop_, propname)) {
|
||||||
mesh_.add_property(prop_, propname);
|
PropertyManager::mesh().add_property(prop_, propname);
|
||||||
set_range(mesh_.all_elements<Handle>(), intial_value);
|
set_range(mesh_.all_elements<Handle>(), intial_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,8 +203,8 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
* @param mesh The mesh on which to create the property.
|
* @param mesh The mesh on which to create the property.
|
||||||
*/
|
*/
|
||||||
PropertyManager(PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
PropertyManager(const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||||
mesh_.add_property(prop_, name_);
|
PropertyManager::mesh().add_property(prop_, name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,8 +215,8 @@ class PropertyManager {
|
|||||||
* @param initial_value The property will be initialized with intial_value.
|
* @param initial_value The property will be initialized with intial_value.
|
||||||
* @param mesh The mesh on which to create the property.
|
* @param mesh The mesh on which to create the property.
|
||||||
*/
|
*/
|
||||||
PropertyManager(const Value& intial_value, PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
PropertyManager(const Value& intial_value, const PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||||
mesh_.add_property(prop_, name_);
|
PropertyManager::mesh().add_property(prop_, name_);
|
||||||
set_range(mesh_.all_elements<Handle>(), intial_value);
|
set_range(mesh_.all_elements<Handle>(), intial_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +245,7 @@ class PropertyManager {
|
|||||||
}
|
}
|
||||||
else // unnamed property -> create a property manager refering to a new property and copy the contents
|
else // unnamed property -> create a property manager refering to a new property and copy the contents
|
||||||
{
|
{
|
||||||
mesh_.add_property(prop_, name_);
|
PropertyManager::mesh().add_property(prop_, name_);
|
||||||
Storage::copy(rhs, *this);
|
Storage::copy(rhs, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,9 +294,9 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template <typename MeshType >
|
template <typename MeshType >
|
||||||
MeshType& getMesh() const { return dynamic_cast<MeshType&>(mesh_); }
|
const MeshType& getMesh() const { return dynamic_cast<MeshType&>(mesh_); }
|
||||||
|
|
||||||
MeshT& getMesh() const { return dynamic_cast<MeshT&>(mesh_); }
|
const MeshT& getMesh() const { return dynamic_cast<MeshT&>(mesh_); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move constructor. Transfers ownership (delete responsibility).
|
* Move constructor. Transfers ownership (delete responsibility).
|
||||||
@@ -317,7 +329,7 @@ class PropertyManager {
|
|||||||
// swap the data stored in the properties
|
// swap the data stored in the properties
|
||||||
Storage::swap(rhs, *this);
|
Storage::swap(rhs, *this);
|
||||||
// remove the property from rhs
|
// remove the property from rhs
|
||||||
rhs.mesh_.remove_property(rhs.prop_);
|
rhs.mesh().remove_property(rhs.prop_);
|
||||||
// invalidate prop_
|
// invalidate prop_
|
||||||
rhs.prop_.invalidate();
|
rhs.prop_.invalidate();
|
||||||
}
|
}
|
||||||
@@ -373,18 +385,6 @@ class PropertyManager {
|
|||||||
mesh, propname, range.begin(), range.end(), init_value);
|
mesh, propname, range.begin(), range.end(), init_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyManager duplicate(const char *clone_name) {
|
|
||||||
PropertyManager pm(mesh_, clone_name, false);
|
|
||||||
pm.mesh_.property(pm.prop_) = mesh_.property(prop_);
|
|
||||||
return pm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Included for backwards compatibility with non-C++11 version.
|
|
||||||
*/
|
|
||||||
PropertyManager move() {
|
|
||||||
return std::move(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access the value of the encapsulated mesh property.
|
* Access the value of the encapsulated mesh property.
|
||||||
@@ -399,7 +399,7 @@ class PropertyManager {
|
|||||||
* @note This method is only used for mesh properties.
|
* @note This method is only used for mesh properties.
|
||||||
*/
|
*/
|
||||||
typename PROPTYPE::reference& operator*() {
|
typename PROPTYPE::reference& operator*() {
|
||||||
return mesh_.mproperty(prop_)[0];
|
return mesh().mproperty(prop_)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -415,7 +415,7 @@ class PropertyManager {
|
|||||||
* @note This method is only used for mesh properties.
|
* @note This method is only used for mesh properties.
|
||||||
*/
|
*/
|
||||||
typename PROPTYPE::const_reference& operator*() const {
|
typename PROPTYPE::const_reference& operator*() const {
|
||||||
return mesh_.mproperty(prop_)[0];
|
return mesh().mproperty(prop_)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -425,9 +425,8 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
||||||
*/
|
*/
|
||||||
template<typename HandleType>
|
inline typename PROPTYPE::reference operator[] (Handle handle) {
|
||||||
inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
|
return mesh().property(prop_, handle);
|
||||||
return mesh_.property(prop_, handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -437,9 +436,8 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
||||||
*/
|
*/
|
||||||
template<typename HandleType>
|
inline typename PROPTYPE::const_reference operator[] (const Handle& handle) const {
|
||||||
inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
|
return mesh().property(prop_, handle);
|
||||||
return mesh_.property(prop_, handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,9 +447,9 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
||||||
*/
|
*/
|
||||||
template<typename HandleType>
|
inline typename PROPTYPE::reference operator() (const Handle& handle = Handle()) {
|
||||||
inline typename PROPTYPE::reference operator() (const HandleType &handle) {
|
// return mesh().property(prop_, handle);
|
||||||
return mesh_.property(prop_, handle);
|
return Storage::access_property(mesh(), prop_, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -461,9 +459,9 @@ class PropertyManager {
|
|||||||
*
|
*
|
||||||
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
* @param handle A handle of the appropriate handle type. (I.e. \p VertexHandle for \p VPropHandleT, etc.)
|
||||||
*/
|
*/
|
||||||
template<typename HandleType>
|
inline typename PROPTYPE::const_reference operator() (const Handle& handle = Handle()) const {
|
||||||
inline typename PROPTYPE::const_reference operator() (const HandleType &handle) const {
|
// return mesh().property(prop_, handle);
|
||||||
return mesh_.property(prop_, handle);
|
return Storage::access_property_const(mesh(), prop_, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -571,16 +569,50 @@ class PropertyManager {
|
|||||||
private:
|
private:
|
||||||
void deleteProperty() {
|
void deleteProperty() {
|
||||||
if (!retain_ && prop_.is_valid())
|
if (!retain_ && prop_.is_valid())
|
||||||
mesh_.remove_property(prop_);
|
mesh().remove_property(prop_);
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyConnectivity& mesh() const
|
||||||
|
{
|
||||||
|
return const_cast<PolyConnectivity&>(mesh_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PolyConnectivity& mesh_;
|
const PolyConnectivity& mesh_;
|
||||||
PROPTYPE prop_;
|
PROPTYPE prop_;
|
||||||
bool retain_;
|
bool retain_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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_;
|
||||||
|
};
|
||||||
|
|
||||||
/** @relates PropertyManager
|
/** @relates PropertyManager
|
||||||
*
|
*
|
||||||
* @deprecated Temporary properties should not have a name.
|
* @deprecated Temporary properties should not have a name.
|
||||||
@@ -852,6 +884,16 @@ getPointsProperty(MeshT &mesh) {
|
|||||||
return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
|
return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @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());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename HandleT, typename T>
|
template <typename HandleT, typename T>
|
||||||
using Prop = PropertyManager<typename PropHandle<HandleT>::template type<T>>;
|
using Prop = PropertyManager<typename PropHandle<HandleT>::template type<T>>;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
//#define ENABLE_PROPERTY_TIMING_OUTPUT
|
||||||
|
#ifdef ENABLE_PROPERTY_TIMING_OUTPUT
|
||||||
|
#define TIMING_OUTPUT(X) X
|
||||||
|
#else
|
||||||
|
#define TIMING_OUTPUT(X)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class OpenMeshPropertyManager : public OpenMeshBase {
|
class OpenMeshPropertyManager : public OpenMeshBase {
|
||||||
@@ -228,7 +235,7 @@ TEST_F(OpenMeshPropertyManager, property_move_construction) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
auto prop2 = std::move(prop1);
|
auto prop2 = std::move(prop1);
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "move constructing property from temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "move constructing property from temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_FALSE(prop1.isValid()) << "prop1 should have been invalidated";
|
EXPECT_FALSE(prop1.isValid()) << "prop1 should have been invalidated";
|
||||||
|
|
||||||
@@ -244,7 +251,7 @@ TEST_F(OpenMeshPropertyManager, property_move_construction) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
auto prop2 = std::move(prop1); // prop1 and prop2 should refere to the same property
|
auto prop2 = std::move(prop1); // prop1 and prop2 should refere to the same property
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "move constructing from named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "move constructing from named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named properties cannot be invalidated";
|
EXPECT_TRUE(prop1.isValid()) << "named properties cannot be invalidated";
|
||||||
|
|
||||||
@@ -279,7 +286,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||||
|
|
||||||
@@ -303,7 +310,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||||
|
|
||||||
@@ -328,7 +335,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
prop1.set_range(mesh_.vertices(), 0);
|
prop1.set_range(mesh_.vertices(), 0);
|
||||||
|
|
||||||
@@ -351,7 +358,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
prop1.set_range(mesh_.vertices(), 0);
|
prop1.set_range(mesh_.vertices(), 0);
|
||||||
|
|
||||||
@@ -372,7 +379,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1; // this should be a no op
|
prop2 = prop1; // this should be a no op
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||||
@@ -417,7 +424,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // this should be cheap
|
prop2 = std::move(prop1); // this should be cheap
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||||
|
|
||||||
@@ -439,7 +446,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1);
|
prop2 = std::move(prop1);
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||||
|
|
||||||
@@ -462,7 +469,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -487,7 +494,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -510,7 +517,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // this should be a no op
|
prop2 = std::move(prop1); // this should be a no op
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -553,7 +560,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||||
|
|
||||||
@@ -578,7 +585,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||||
|
|
||||||
@@ -603,7 +610,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
prop1.set_range(mesh_.vertices(), 0);
|
prop1.set_range(mesh_.vertices(), 0);
|
||||||
|
|
||||||
@@ -626,7 +633,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1;
|
prop2 = prop1;
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
prop1.set_range(mesh_.vertices(), 0);
|
prop1.set_range(mesh_.vertices(), 0);
|
||||||
|
|
||||||
@@ -646,7 +653,7 @@ TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = prop1; // this should be a no op
|
prop2 = prop1; // this should be a no op
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||||
@@ -687,7 +694,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // this should be cheap
|
prop2 = std::move(prop1); // this should be cheap
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||||
|
|
||||||
@@ -710,7 +717,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1);
|
prop2 = std::move(prop1);
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||||
|
|
||||||
@@ -733,7 +740,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -758,7 +765,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -783,7 +790,7 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
auto t_start = std::chrono::high_resolution_clock::now();
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
prop2 = std::move(prop1); // should copy
|
prop2 = std::move(prop1); // should copy
|
||||||
auto t_end = std::chrono::high_resolution_clock::now();
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
TIMING_OUTPUT(std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||||
|
|
||||||
@@ -803,5 +810,63 @@ TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(OpenMeshPropertyManager, temporary_property_on_const_mesh) {
|
||||||
|
|
||||||
|
const auto& const_ref = mesh_;
|
||||||
|
|
||||||
|
auto cog = OpenMesh::FProp<Mesh::Point>(const_ref);
|
||||||
|
auto points = OpenMesh::getPointsProperty(const_ref);
|
||||||
|
|
||||||
|
for (auto fh : const_ref.faces())
|
||||||
|
cog(fh) = fh.vertices().avg(points);
|
||||||
|
|
||||||
|
auto cog_copy = cog;
|
||||||
|
|
||||||
|
for (auto fh : const_ref.faces())
|
||||||
|
{
|
||||||
|
EXPECT_NE(&cog(fh), &cog_copy(fh)) << "Both properties point to the same memory";
|
||||||
|
EXPECT_EQ(cog(fh), cog_copy(fh)) << "Property not copied correctly";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto description = OpenMesh::MProp<std::string>(const_ref);
|
||||||
|
description() = "Cool Const Mesh";
|
||||||
|
|
||||||
|
std::cout << description(OpenMesh::MeshHandle(33)) << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenMesh::VProp<int> get_id_prop(const OpenMesh::PolyConnectivity& mesh)
|
||||||
|
{
|
||||||
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto id_prop = OpenMesh::VProp<int>(mesh);
|
||||||
|
for (auto vh : mesh.vertices())
|
||||||
|
id_prop(vh) = vh.idx();
|
||||||
|
|
||||||
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
|
TIMING_OUTPUT(std::cout << "Time spend in function: " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
|
return id_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(OpenMeshPropertyManager, return_property_from_function) {
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000000; ++i)
|
||||||
|
mesh_.add_vertex(Mesh::Point());
|
||||||
|
|
||||||
|
auto t_start = std::chrono::high_resolution_clock::now();
|
||||||
|
auto id_p = get_id_prop(mesh_);
|
||||||
|
auto t_end = std::chrono::high_resolution_clock::now();
|
||||||
|
TIMING_OUTPUT(std::cout << "Time spend around function " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;)
|
||||||
|
|
||||||
|
for (auto vh : mesh_.vertices())
|
||||||
|
{
|
||||||
|
EXPECT_EQ(id_p(vh), vh.idx()) << "Property not returned correctly" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user