Merge branch 'master' into remove_compile_order_check
This commit is contained in:
@@ -11,41 +11,63 @@ endif()
|
||||
|
||||
if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
# Search for gtest headers and libraries
|
||||
find_package(GoogleTest)
|
||||
find_package(GTest)
|
||||
|
||||
if(GTEST_FOUND)
|
||||
|
||||
enable_testing()
|
||||
|
||||
find_package(EIGEN3)
|
||||
|
||||
# Set correct include paths so that the compiler can find the headers
|
||||
include_directories(${GTEST_INCLUDE_DIRS})
|
||||
include_directories(${GTEST_INCLUDE_DIRS} )
|
||||
|
||||
|
||||
# set additional link directories
|
||||
link_directories(${GTEST_LIBRARY_DIR} )
|
||||
|
||||
|
||||
if (EIGEN3_FOUND)
|
||||
add_definitions( -DENABLE_EIGEN3_TEST )
|
||||
include_directories(${EIGEN3_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if ( CMAKE_GENERATOR MATCHES "^Visual Studio 11.*" )
|
||||
add_definitions( /D _VARIADIC_MAX=10 )
|
||||
endif()
|
||||
|
||||
# Create new target named unittests_hexmeshing
|
||||
FILE(GLOB UNITTEST_SRC *.cc)
|
||||
# Create unittest executable
|
||||
acg_add_executable(unittests ${UNITTEST_SRC})
|
||||
# Create unittest executable
|
||||
acg_add_executable(unittests ${UNITTEST_SRC})
|
||||
acg_add_executable(unittests_customvec ${UNITTEST_SRC})
|
||||
acg_add_executable(unittests_doublevec ${UNITTEST_SRC})
|
||||
target_compile_definitions(unittests_customvec PRIVATE TEST_CUSTOM_TRAITS)
|
||||
target_compile_definitions(unittests_doublevec PRIVATE TEST_DOUBLE_TRAITS)
|
||||
|
||||
# For the unittest we don't want the install rpath as set by acg_add_executable
|
||||
set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
# For the unittest we don't want the install rpath as set by acg_add_executable
|
||||
set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
set_target_properties ( unittests_customvec PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
set_target_properties ( unittests_doublevec PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
|
||||
# Set output directory to ${BINARY_DIR}/Unittests
|
||||
set (OUTPUT_DIR "${CMAKE_BINARY_DIR}/Unittests")
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_doublevec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${CONFIG} UPCONFIG)
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_doublevec PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
endforeach()
|
||||
|
||||
|
||||
if ( NOT WIN32)
|
||||
# Link against all necessary libraries
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
target_link_libraries(unittests_doublevec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +77,9 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
add_definitions( -DOPENMESHDLL )
|
||||
|
||||
endif()
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests_doublevec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -63,10 +87,13 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
if ( NOT WIN32 )
|
||||
# Set compiler flags
|
||||
set_target_properties(unittests PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
set_target_properties(unittests_doublevec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
else()
|
||||
# Set compiler flags
|
||||
set_target_properties(unittests PROPERTIES COMPILE_FLAGS "" )
|
||||
|
||||
set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "" )
|
||||
set_target_properties(unittests_doublevec PROPERTIES COMPILE_FLAGS "" )
|
||||
endif()
|
||||
|
||||
if ( OPENMESH_BUILD_SHARED )
|
||||
@@ -80,12 +107,26 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
"$<TARGET_FILE:${TAR}>"
|
||||
"${CMAKE_BINARY_DIR}/Unittests/$<TARGET_FILE_NAME:${TAR}>"
|
||||
COMMENT "Copying OpenMesh targets to unittests directory")
|
||||
add_custom_command(TARGET unittests_customvec POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${TAR}>"
|
||||
"${CMAKE_BINARY_DIR}/Unittests/$<TARGET_FILE_NAME:${TAR}>"
|
||||
COMMENT "Copying OpenMesh targets to unittests directory")
|
||||
add_custom_command(TARGET unittests_doublevec POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${TAR}>"
|
||||
"${CMAKE_BINARY_DIR}/Unittests/$<TARGET_FILE_NAME:${TAR}>"
|
||||
COMMENT "Copying OpenMesh targets to unittests directory")
|
||||
endforeach(TAR)
|
||||
endif()
|
||||
|
||||
acg_copy_after_build(unittests ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
acg_copy_after_build(unittests_customvec ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
acg_copy_after_build(unittests_doublevec ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests")
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests_with_minimal_vector WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests_customvec")
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests_with_double_vector WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests_doublevec")
|
||||
|
||||
else(GTEST_FOUND)
|
||||
message(STATUS "Google testing framework was not found, unittests disabled.")
|
||||
|
||||
BIN
src/Unittests/TestFiles/cube-minimal-custom_props-binary.ply
Normal file
BIN
src/Unittests/TestFiles/cube-minimal-custom_props-binary.ply
Normal file
Binary file not shown.
33
src/Unittests/TestFiles/cube-minimal-faceColors.ply
Normal file
33
src/Unittests/TestFiles/cube-minimal-faceColors.ply
Normal file
@@ -0,0 +1,33 @@
|
||||
ply
|
||||
format ascii 1.0
|
||||
comment VCGLIB generated
|
||||
element vertex 8
|
||||
property float x
|
||||
property float y
|
||||
property float z
|
||||
element face 12
|
||||
property list uchar int vertex_indices
|
||||
property float red
|
||||
property float green
|
||||
property float blue
|
||||
end_header
|
||||
-1 -1 -1
|
||||
1 -1 -1
|
||||
1 1 -1
|
||||
-1 1 -1
|
||||
-1 -1 1
|
||||
1 -1 1
|
||||
1 1 1
|
||||
-1 1 1
|
||||
3 0 1 2 0.419608 0.462745 0.698039
|
||||
3 0 2 3 1.0 0.552941 0.419608
|
||||
3 5 4 7 0.698039 1.0 0.619608
|
||||
3 5 7 6 0.419608 1.0 0.529412
|
||||
3 6 2 1 0.643137 0.419608 0.698039
|
||||
3 6 1 5 0.643137 0.419608 1.0
|
||||
3 3 7 4 0.698039 0.552941 1.0
|
||||
3 3 4 0 1.0 0.552941 0.419608
|
||||
3 7 3 2 0.419608 0.698039 1.0
|
||||
3 7 2 6 0.419608 0.698039 0.529412
|
||||
3 5 1 0 1.0 0.419608 1.0
|
||||
3 5 0 4 0.698039 1.0 1.0
|
||||
22576
src/Unittests/TestFiles/cube_noisy.off
Normal file
22576
src/Unittests/TestFiles/cube_noisy.off
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/Unittests/TestFiles/cube_poly_version_1_2.om
Normal file
BIN
src/Unittests/TestFiles/cube_poly_version_1_2.om
Normal file
Binary file not shown.
BIN
src/Unittests/TestFiles/cube_poly_version_2_0.om
Normal file
BIN
src/Unittests/TestFiles/cube_poly_version_2_0.om
Normal file
Binary file not shown.
BIN
src/Unittests/TestFiles/cube_tri_version_1_2.om
Normal file
BIN
src/Unittests/TestFiles/cube_tri_version_1_2.om
Normal file
Binary file not shown.
BIN
src/Unittests/TestFiles/cube_tri_version_2_0.om
Normal file
BIN
src/Unittests/TestFiles/cube_tri_version_2_0.om
Normal file
Binary file not shown.
BIN
src/Unittests/TestFiles/cube_tri_version_7_5.om
Normal file
BIN
src/Unittests/TestFiles/cube_tri_version_7_5.om
Normal file
Binary file not shown.
1271
src/Unittests/TestFiles/sphere840.ply
Normal file
1271
src/Unittests/TestFiles/sphere840.ply
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,16 @@
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
|
||||
#ifdef TEST_CUSTOM_TRAITS
|
||||
#include <Unittests/unittests_common_customtraits.hh>
|
||||
#elif defined(TEST_DOUBLE_TRAITS)
|
||||
struct CustomTraits : public OpenMesh::DefaultTraitsDouble {
|
||||
};
|
||||
#else
|
||||
struct CustomTraits : public OpenMesh::DefaultTraits {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
typedef OpenMesh::TriMesh_ArrayKernelT<CustomTraits> Mesh;
|
||||
|
||||
|
||||
139
src/Unittests/unittests_common_customtraits.hh
Normal file
139
src/Unittests/unittests_common_customtraits.hh
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifndef UNITTESTS_COMMON_DUMMYTRAITS
|
||||
#define UNITTESTS_COMMON_DUMMYTRAITS
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Utils/color_cast.hh>
|
||||
#include <array>
|
||||
|
||||
namespace Custom {
|
||||
|
||||
/// A Vector class with the absolute minimum of built-in methods to test the
|
||||
/// interface expected from Vectors used in Traits
|
||||
template <int DIM> class Vec {
|
||||
public:
|
||||
// Constructor with DIM components
|
||||
Vec(float x) : data({ x }) {}
|
||||
Vec(float x, float y) : data({ x, y }) {}
|
||||
Vec(float x, float y, float z) : data({{ x, y, z }}) {}
|
||||
Vec(float x, float y, float z, float w) : data({ x, y, z, w }) {}
|
||||
|
||||
Vec() = default;
|
||||
Vec(Vec<DIM> const &) = default;
|
||||
|
||||
float &operator[](int i) { return data[i]; }
|
||||
float operator[](int i) const { return data[i]; }
|
||||
|
||||
private:
|
||||
std::array<float, DIM> data;
|
||||
};
|
||||
|
||||
template <int DIM> bool operator==(Vec<DIM> const &lhs, Vec<DIM> const &rhs) {
|
||||
for (int i = 0; i < DIM; i++)
|
||||
if (lhs[i] != rhs[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int DIM>
|
||||
Vec<DIM> operator+(Vec<DIM> const &lhs, Vec<DIM> const &rhs) {
|
||||
Vec<DIM> result;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
result[i] = lhs[i] + rhs[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
template <int DIM>
|
||||
Vec<DIM> operator-(Vec<DIM> const &lhs, Vec<DIM> const &rhs) {
|
||||
Vec<DIM> result;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
result[i] = lhs[i] - rhs[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> operator*(Vec<DIM> const &lhs, float rhs) {
|
||||
Vec<DIM> result;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
result[i] = lhs[i] * rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> operator*(float lhs, Vec<DIM> const &rhs) {
|
||||
return rhs * lhs;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> operator/(Vec<DIM> const &lhs, float rhs) {
|
||||
Vec<DIM> result;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
result[i] = lhs[i] / rhs;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> &operator+=(Vec<DIM> &lhs, Vec<DIM> const &rhs) {
|
||||
return lhs = lhs + rhs;
|
||||
}
|
||||
template <int DIM> Vec<DIM> &operator-=(Vec<DIM> &lhs, Vec<DIM> const &rhs) {
|
||||
return lhs = lhs - rhs;
|
||||
}
|
||||
template <int DIM> Vec<DIM> &operator*=(Vec<DIM> &lhs, float rhs) {
|
||||
return lhs = lhs * rhs;
|
||||
}
|
||||
template <int DIM> Vec<DIM> &operator/=(Vec<DIM> &lhs, float rhs) {
|
||||
return lhs = lhs / rhs;
|
||||
}
|
||||
|
||||
template <int DIM> float norm(Vec<DIM> const &v) {
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
sum += v[i] * v[i];
|
||||
return std::sqrt(sum);
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> &normalize(Vec<DIM> &v) { return v /= norm(v); }
|
||||
template <int DIM> Vec<DIM> &vectorize(Vec<DIM> &v, float val) {
|
||||
for (int i = 0; i < DIM; i++)
|
||||
v[i] = val;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> &minimize(Vec<DIM> &v1, Vec<DIM> const &v2) {
|
||||
for (int i = 0; i < DIM; i++)
|
||||
v1[i] = std::min(v1[i], v2[i]);
|
||||
return v1;
|
||||
}
|
||||
|
||||
template <int DIM> Vec<DIM> &maximize(Vec<DIM> &v1, Vec<DIM> const &v2) {
|
||||
for (int i = 0; i < DIM; i++)
|
||||
v1[i] = std::max(v1[i], v2[i]);
|
||||
return v1;
|
||||
}
|
||||
|
||||
template <int DIM> float dot(Vec<DIM> const &v1, Vec<DIM> const &v2) {
|
||||
float sum = 0.f;
|
||||
for (int i = 0; i < DIM; i++)
|
||||
sum += v1[i] * v2[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
inline Vec<3> cross(Vec<3> const &v1, Vec<3> const &v2) {
|
||||
return {v1[1] * v2[2] - v1[2] * v2[1], //
|
||||
v1[2] * v2[0] - v1[0] * v2[2], //
|
||||
v1[0] * v2[1] - v1[1] * v2[0]};
|
||||
}
|
||||
}
|
||||
|
||||
namespace OpenMesh {
|
||||
template <int DIM> struct vector_traits<Custom::Vec<DIM>> {
|
||||
using vector_type = Custom::Vec<DIM>;
|
||||
using value_type = float;
|
||||
static const size_t size_ = DIM;
|
||||
static size_t size() { return size_; }
|
||||
};
|
||||
}
|
||||
|
||||
struct CustomTraits : public OpenMesh::DefaultTraits {
|
||||
typedef Custom::Vec<3> Point;
|
||||
typedef Custom::Vec<3> Normal;
|
||||
|
||||
typedef Custom::Vec<2> TexCoord2D;
|
||||
typedef Custom::Vec<3> TexCoord3D;
|
||||
};
|
||||
|
||||
#endif // UNITTESTS_COMMON_DUMMYTRAITS
|
||||
@@ -285,19 +285,15 @@ TEST_F(OpenMeshConvertPolyMeshToTriangle, EdgePropertyCheckDouble) {
|
||||
// Check if it is ok.
|
||||
Mesh::EdgeIter v_it = p.edges_begin();
|
||||
|
||||
if(p.is_boundary( (*v_it) ))
|
||||
EXPECT_EQ( p.property(doubleHandle,*v_it) , 0.0 ) << "Invalid double value for vertex 0";
|
||||
++v_it;
|
||||
|
||||
if(p.is_boundary( (*v_it) ))
|
||||
EXPECT_EQ( p.property(doubleHandle,*v_it) , 1.0 ) << "Invalid double value for vertex 1";
|
||||
++v_it;
|
||||
|
||||
if(p.is_boundary( (*v_it) ))
|
||||
EXPECT_EQ( p.property(doubleHandle,*v_it) , 2.0 ) << "Invalid double value for vertex 2";
|
||||
++v_it;
|
||||
|
||||
if(p.is_boundary( (*v_it) ))
|
||||
EXPECT_EQ( p.property(doubleHandle,*v_it) , 3.0 ) << "Invalid double value for vertex 3";
|
||||
++v_it;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
||||
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
|
||||
#include <OpenMesh/Tools/Decimater/ModNormalDeviationT.hh>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -49,7 +50,7 @@ TEST_F(OpenMeshDecimater, DecimateMesh) {
|
||||
decimaterDBG.initialize();
|
||||
size_t removedVertices = 0;
|
||||
removedVertices = decimaterDBG.decimate_to(5000);
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
|
||||
EXPECT_EQ(2526u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ(5000u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
@@ -72,7 +73,7 @@ TEST_F(OpenMeshDecimater, DecimateMeshToFaceVerticesLimit) {
|
||||
decimaterDBG.initialize();
|
||||
size_t removedVertices = 0;
|
||||
removedVertices = decimaterDBG.decimate_to_faces(5000, 8000);
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
|
||||
EXPECT_EQ(2526u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ(5000u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
@@ -95,7 +96,7 @@ TEST_F(OpenMeshDecimater, DecimateMeshToFaceFaceLimit) {
|
||||
decimaterDBG.initialize();
|
||||
size_t removedVertices = 0;
|
||||
removedVertices = decimaterDBG.decimate_to_faces(4500, 9996);
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
|
||||
EXPECT_EQ(2526u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ(5000u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
@@ -103,6 +104,34 @@ TEST_F(OpenMeshDecimater, DecimateMeshToFaceFaceLimit) {
|
||||
EXPECT_EQ(9996u, mesh_.n_faces()) << "The number of faces after decimation is not correct!";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshDecimater, DecimateMeshToVertexLimitWithLowNormalDeviation) {
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");
|
||||
|
||||
ASSERT_TRUE(ok);
|
||||
|
||||
typedef OpenMesh::Decimater::DecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalDeviationT< Mesh >::Handle HModNormalDeviation;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
decimaterDBG.add( hModQuadricDBG );
|
||||
HModNormalDeviation hModNormalDeviation;
|
||||
decimaterDBG.add( hModNormalDeviation );
|
||||
decimaterDBG.module(hModNormalDeviation).set_normal_deviation(15.0);
|
||||
decimaterDBG.initialize();
|
||||
size_t removedVertices = 0;
|
||||
removedVertices = decimaterDBG.decimate_to(8);
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
|
||||
EXPECT_EQ(6998u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ( 528u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
EXPECT_EQ(1578u, mesh_.n_edges()) << "The number of edges after decimation is not correct!";
|
||||
EXPECT_EQ(1052u, mesh_.n_faces()) << "The number of faces after decimation is not correct!";
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshDecimater, DecimateMeshExampleFromDoc) {
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");
|
||||
@@ -121,7 +150,7 @@ TEST_F(OpenMeshDecimater, DecimateMeshExampleFromDoc) {
|
||||
decimaterDBG.initialize();
|
||||
size_t removedVertices = 0;
|
||||
removedVertices = decimaterDBG.decimate_to_faces(4500, 9996);
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
decimaterDBG.mesh().garbage_collection();
|
||||
|
||||
EXPECT_EQ(2526u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ(5000u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
@@ -134,7 +163,7 @@ class UnittestObserver : public OpenMesh::Decimater::Observer
|
||||
size_t notifies_;
|
||||
size_t all_steps_;
|
||||
public:
|
||||
UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
explicit UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
|
||||
void notify(size_t _step)
|
||||
{
|
||||
|
||||
271
src/Unittests/unittests_eigen3_type.cc
Normal file
271
src/Unittests/unittests_eigen3_type.cc
Normal file
@@ -0,0 +1,271 @@
|
||||
|
||||
#ifdef ENABLE_EIGEN3_TEST
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <iostream>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
||||
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
|
||||
#include <OpenMesh/Tools/Decimater/ModNormalDeviationT.hh>
|
||||
|
||||
#include <OpenMesh/Core/Geometry/EigenVectorT.hh>
|
||||
|
||||
struct EigenTraits : OpenMesh::DefaultTraits {
|
||||
using Point = Eigen::Vector3d;
|
||||
using Normal = Eigen::Vector3d;
|
||||
|
||||
using TexCoord2D = Eigen::Vector2d;
|
||||
};
|
||||
|
||||
using EigenTriMesh = OpenMesh::TriMesh_ArrayKernelT<EigenTraits>;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class OpenMeshEigenTest : public testing::Test {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
// Do some initial stuff with the member data here...
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
EigenTriMesh mesh_;
|
||||
};
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_vectorize) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal;
|
||||
|
||||
vectorize(normal,2);
|
||||
|
||||
EXPECT_EQ(normal[0],2.0f ) << "Wrong x value";
|
||||
EXPECT_EQ(normal[1],2.0f ) << "Wrong y value";
|
||||
EXPECT_EQ(normal[2],2.0f ) << "Wrong z value";
|
||||
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_norm) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal(1,0,0);
|
||||
|
||||
EigenTriMesh::Scalar result = norm(normal);
|
||||
|
||||
EXPECT_EQ(result,1.0f ) << "Wrong norm";
|
||||
|
||||
normal = EigenTriMesh::Normal(2,0,0);
|
||||
|
||||
result = norm(normal);
|
||||
|
||||
EXPECT_EQ(result,2.0f ) << "Wrong norm";
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_sqrnorm) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal(1,0,0);
|
||||
|
||||
EigenTriMesh::Scalar result = sqrnorm(normal);
|
||||
|
||||
EXPECT_EQ(result,1.0f ) << "Wrong norm";
|
||||
|
||||
normal = EigenTriMesh::Normal(2,0,0);
|
||||
|
||||
result = sqrnorm(normal);
|
||||
|
||||
EXPECT_EQ(result,4.0f ) << "Wrong norm";
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_normalize) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal(2,0,0);
|
||||
|
||||
normalize(normal);
|
||||
|
||||
EXPECT_EQ(norm(normal),1.0f ) << "Wrong norm after normalization";
|
||||
|
||||
normal = EigenTriMesh::Normal(2,6,9);
|
||||
|
||||
normalize(normal);
|
||||
|
||||
EXPECT_EQ(norm(normal),1.0f ) << "Wrong norm after normalization";
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_cross_Product) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal1(1,0,0);
|
||||
EigenTriMesh::Normal normal2(1,1,0);
|
||||
|
||||
EigenTriMesh::Normal result = cross(normal1,normal2);
|
||||
|
||||
EXPECT_EQ(result[0],0.0f ) << "Wrong result x direction";
|
||||
EXPECT_EQ(result[1],0.0f ) << "Wrong result y direction";
|
||||
EXPECT_EQ(result[2],1.0f ) << "Wrong result z direction";
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_external_dot_Product) {
|
||||
|
||||
|
||||
EigenTriMesh::Normal normal1(1,0,0);
|
||||
EigenTriMesh::Normal normal2(1,1,0);
|
||||
EigenTriMesh::Normal normal3(1,1,1);
|
||||
EigenTriMesh::Normal normal4(2,4,6);
|
||||
|
||||
EigenTriMesh::Scalar result = dot(normal1,normal2);
|
||||
EigenTriMesh::Scalar result1 = dot(normal3,normal4);
|
||||
|
||||
EXPECT_EQ(result,1.0f ) << "Wrong dot product";
|
||||
EXPECT_EQ(result1,12.0f ) << "Wrong dot product";
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshEigenTest, Test_Basic_setup) {
|
||||
|
||||
// Add some vertices
|
||||
EigenTriMesh::VertexHandle vhandle[4];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(EigenTriMesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(EigenTriMesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(EigenTriMesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(EigenTriMesh::Point(1, 0, 0));
|
||||
|
||||
// Add two faces
|
||||
std::vector<EigenTriMesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
EXPECT_EQ(mesh_.n_faces(),2u) << "Wrong number of faces";
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshEigenTest, test_normal_computation) {
|
||||
|
||||
// Add some vertices
|
||||
EigenTriMesh::VertexHandle vhandle[4];
|
||||
|
||||
mesh_.request_vertex_normals();
|
||||
mesh_.request_face_normals();
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(EigenTriMesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(EigenTriMesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(EigenTriMesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(EigenTriMesh::Point(1, 0, 0));
|
||||
|
||||
// Add two faces
|
||||
std::vector<EigenTriMesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
|
||||
EigenTriMesh::FaceHandle face1 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
EigenTriMesh::FaceHandle face2 = mesh_.add_face(face_vhandles);
|
||||
|
||||
mesh_.update_face_normals();
|
||||
|
||||
|
||||
EXPECT_EQ(mesh_.n_faces(),2u) << "Wrong number of faces";
|
||||
|
||||
EigenTriMesh::Normal normal = mesh_.normal(face1);
|
||||
|
||||
EXPECT_EQ(normal[0],0.0f ) << "Wrong normal x direction";
|
||||
EXPECT_EQ(normal[1],0.0f ) << "Wrong normal y direction";
|
||||
EXPECT_EQ(normal[2],1.0f ) << "Wrong normal z direction";
|
||||
|
||||
normal = mesh_.normal(face2);
|
||||
|
||||
EXPECT_EQ(normal[0],0.0f ) << "Wrong normal x direction";
|
||||
EXPECT_EQ(normal[1],0.0f ) << "Wrong normal y direction";
|
||||
EXPECT_EQ(normal[2],1.0f ) << "Wrong normal z direction";
|
||||
|
||||
}
|
||||
|
||||
/* Just load a simple mesh file in obj format and count whether
|
||||
* the right number of entities has been loaded. Afterwards recompute
|
||||
* normals
|
||||
*/
|
||||
TEST_F(OpenMeshEigenTest, LoadSimpleOFFFile) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");
|
||||
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
EXPECT_EQ(7526u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(22572u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(15048u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
mesh_.update_normals();
|
||||
}
|
||||
|
||||
// Test decimation with Eigen as vector type
|
||||
TEST_F(OpenMeshEigenTest, Decimater) {
|
||||
mesh_.clear();
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");
|
||||
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
EXPECT_EQ(7526u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(22572u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(15048u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
mesh_.update_normals();
|
||||
|
||||
OpenMesh::Decimater::DecimaterT<EigenTriMesh> decimater(mesh_);
|
||||
OpenMesh::Decimater::ModQuadricT<EigenTriMesh>::Handle hModQuadric; // use a quadric module
|
||||
OpenMesh::Decimater::ModNormalDeviationT<EigenTriMesh>::Handle hModNormalDeviation; // also use normal deviation module as binary check
|
||||
decimater.add(hModQuadric);
|
||||
decimater.add(hModNormalDeviation);
|
||||
decimater.module(hModQuadric).unset_max_err();
|
||||
decimater.module(hModNormalDeviation).set_normal_deviation(15);
|
||||
decimater.initialize();
|
||||
size_t removedVertices = decimater.decimate_to(8);
|
||||
mesh_.garbage_collection();
|
||||
|
||||
EXPECT_EQ(6998u, removedVertices) << "The number of remove vertices is not correct!";
|
||||
EXPECT_EQ( 528u, mesh_.n_vertices()) << "The number of vertices after decimation is not correct!";
|
||||
EXPECT_EQ(1578u, mesh_.n_edges()) << "The number of edges after decimation is not correct!";
|
||||
EXPECT_EQ(1052u, mesh_.n_faces()) << "The number of faces after decimation is not correct!";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -43,7 +43,6 @@ TEST_F(OpenMeshMultipleChoiceDecimater, DecimateMesh) {
|
||||
|
||||
typedef OpenMesh::Decimater::McDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -67,7 +66,6 @@ TEST_F(OpenMeshMultipleChoiceDecimater, DecimateMeshToFaceVerticesLimit) {
|
||||
|
||||
typedef OpenMesh::Decimater::McDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -91,7 +89,6 @@ TEST_F(OpenMeshMultipleChoiceDecimater, DecimateMeshToFaceFaceLimit) {
|
||||
|
||||
typedef OpenMesh::Decimater::McDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -112,7 +109,7 @@ class UnittestObserver : public OpenMesh::Decimater::Observer
|
||||
size_t notifies_;
|
||||
size_t all_steps_;
|
||||
public:
|
||||
UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
explicit UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
|
||||
void notify(size_t _step)
|
||||
{
|
||||
|
||||
67
src/Unittests/unittests_mesh_type.cc
Normal file
67
src/Unittests/unittests_mesh_type.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Unittests/unittests_common.hh>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class OpenMeshTypeTest_Poly : public OpenMeshBasePoly {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
// Do some initial stuff with the member data here...
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
}
|
||||
};
|
||||
|
||||
class OpenMeshTypeTest_Triangle : public OpenMeshBase {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
// Do some initial stuff with the member data here...
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
TEST_F(OpenMeshTypeTest_Triangle, testTypeFunctions) {
|
||||
|
||||
|
||||
EXPECT_TRUE(mesh_.is_trimesh()) << "Type Error!";
|
||||
EXPECT_FALSE(mesh_.is_polymesh()) << "Type Error!";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshTypeTest_Poly, testTypeFunctions) {
|
||||
|
||||
|
||||
EXPECT_FALSE(mesh_.is_trimesh()) << "Type Error!";
|
||||
EXPECT_TRUE(mesh_.is_polymesh()) << "Type Error!";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -43,7 +43,6 @@ TEST_F(OpenMeshMixedDecimater, DecimateMesh80PercentMc) {
|
||||
|
||||
typedef OpenMesh::Decimater::MixedDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -67,7 +66,6 @@ TEST_F(OpenMeshMixedDecimater, DecimateMeshToFaceVerticesLimit) {
|
||||
|
||||
typedef OpenMesh::Decimater::MixedDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -91,7 +89,6 @@ TEST_F(OpenMeshMixedDecimater, DecimateMeshToFaceFaceLimit) {
|
||||
|
||||
typedef OpenMesh::Decimater::MixedDecimaterT< Mesh > Decimater;
|
||||
typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric;
|
||||
typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal;
|
||||
|
||||
Decimater decimaterDBG(mesh_);
|
||||
HModQuadric hModQuadricDBG;
|
||||
@@ -112,7 +109,7 @@ class UnittestObserver : public OpenMesh::Decimater::Observer
|
||||
size_t notifies_;
|
||||
size_t all_steps_;
|
||||
public:
|
||||
UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
explicit UnittestObserver(size_t _steps) :Observer(_steps), notifies_(0), all_steps_(0) {}
|
||||
|
||||
void notify(size_t _step)
|
||||
{
|
||||
|
||||
@@ -247,7 +247,7 @@ TEST_F(OpenMeshNormals, NormalCalculations_calc_vertex_normal_fast) {
|
||||
mesh_.request_face_normals();
|
||||
|
||||
|
||||
OpenMesh::Vec3f normal;
|
||||
Mesh::Normal normal;
|
||||
|
||||
mesh_.calc_vertex_normal_fast(vhandle[2],normal);
|
||||
|
||||
@@ -304,7 +304,7 @@ TEST_F(OpenMeshNormals, NormalCalculations_calc_vertex_normal_correct) {
|
||||
mesh_.request_halfedge_normals();
|
||||
mesh_.request_face_normals();
|
||||
|
||||
OpenMesh::Vec3f normal;
|
||||
Mesh::Normal normal;
|
||||
|
||||
|
||||
mesh_.calc_vertex_normal_correct(vhandle[2],normal);
|
||||
@@ -361,7 +361,7 @@ TEST_F(OpenMeshNormals, NormalCalculations_calc_vertex_normal_loop) {
|
||||
mesh_.request_halfedge_normals();
|
||||
mesh_.request_face_normals();
|
||||
|
||||
OpenMesh::Vec3f normal;
|
||||
Mesh::Normal normal;
|
||||
|
||||
mesh_.calc_vertex_normal_loop(vhandle[2],normal);
|
||||
|
||||
|
||||
70
src/Unittests/unittests_polymesh_collapse.cc
Normal file
70
src/Unittests/unittests_polymesh_collapse.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenMeshCollapsePoly : public OpenMeshBasePoly {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
}
|
||||
|
||||
// Member already defined in OpenMeshBase
|
||||
//Mesh mesh_;
|
||||
};
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This code tests is_collapse_ok on a double sided triangle. The
|
||||
* test mesh comprises three vertices, that are connected to form two
|
||||
* triangles of opposite orientation. All halfedges should be non collapsable.
|
||||
*/
|
||||
TEST_F(OpenMeshCollapsePoly, CheckCollapseOkDoublesidedTriangle) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
Mesh::VertexHandle vh0 = mesh_.add_vertex(Mesh::Point(0,0,0));
|
||||
Mesh::VertexHandle vh1 = mesh_.add_vertex(Mesh::Point(1,0,0));
|
||||
Mesh::VertexHandle vh2 = mesh_.add_vertex(Mesh::Point(1,1,0));
|
||||
mesh_.add_face(vh0, vh1, vh2);
|
||||
mesh_.add_face(vh0, vh2, vh1);
|
||||
|
||||
|
||||
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_face_status();
|
||||
mesh_.request_edge_status();
|
||||
|
||||
int collapsable = 0;
|
||||
|
||||
for ( const auto hh : mesh_.all_halfedges() )
|
||||
{
|
||||
if (mesh_.is_collapse_ok(hh) )
|
||||
collapsable++;
|
||||
}
|
||||
|
||||
|
||||
EXPECT_EQ(collapsable,0) << "No collapse should be ok when we have only a double sided Triangle";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -746,5 +746,111 @@ TEST_F(OpenMeshProperties, PropertyIterators ) {
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshProperties, MeshAssignment ) {
|
||||
|
||||
mesh_.clear();
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
auto copy = mesh_;
|
||||
|
||||
copy.request_vertex_status();
|
||||
copy.request_vertex_normals();
|
||||
copy.request_vertex_colors();
|
||||
copy.request_vertex_texcoords1D();
|
||||
copy.request_vertex_texcoords2D();
|
||||
copy.request_vertex_texcoords3D();
|
||||
copy.request_halfedge_status();
|
||||
copy.request_halfedge_texcoords1D();
|
||||
copy.request_halfedge_texcoords2D();
|
||||
copy.request_halfedge_texcoords3D();
|
||||
copy.request_edge_status();
|
||||
copy.request_edge_colors();
|
||||
copy.request_halfedge_normals();
|
||||
copy.request_halfedge_colors();
|
||||
copy.request_face_status();
|
||||
copy.request_face_normals();
|
||||
copy.request_face_colors();
|
||||
copy.request_face_texture_index();
|
||||
|
||||
EXPECT_TRUE(copy.has_vertex_status());
|
||||
EXPECT_TRUE(copy.has_vertex_normals());
|
||||
EXPECT_TRUE(copy.has_vertex_colors());
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords1D());
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords2D());
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords3D());
|
||||
EXPECT_TRUE(copy.has_halfedge_status());
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords1D());
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords2D());
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords3D());
|
||||
EXPECT_TRUE(copy.has_edge_status());
|
||||
EXPECT_TRUE(copy.has_edge_colors());
|
||||
EXPECT_TRUE(copy.has_halfedge_normals());
|
||||
EXPECT_TRUE(copy.has_halfedge_colors());
|
||||
EXPECT_TRUE(copy.has_face_status());
|
||||
EXPECT_TRUE(copy.has_face_normals());
|
||||
EXPECT_TRUE(copy.has_face_colors());
|
||||
EXPECT_TRUE(copy.has_face_texture_index());
|
||||
|
||||
copy.assign(mesh_, true);
|
||||
|
||||
EXPECT_FALSE(copy.has_vertex_status());
|
||||
EXPECT_FALSE(copy.has_vertex_normals());
|
||||
EXPECT_FALSE(copy.has_vertex_colors());
|
||||
EXPECT_FALSE(copy.has_vertex_texcoords1D());
|
||||
EXPECT_FALSE(copy.has_vertex_texcoords2D());
|
||||
EXPECT_FALSE(copy.has_vertex_texcoords3D());
|
||||
EXPECT_FALSE(copy.has_halfedge_status());
|
||||
EXPECT_FALSE(copy.has_halfedge_texcoords1D());
|
||||
EXPECT_FALSE(copy.has_halfedge_texcoords2D());
|
||||
EXPECT_FALSE(copy.has_halfedge_texcoords3D());
|
||||
EXPECT_FALSE(copy.has_edge_status());
|
||||
EXPECT_FALSE(copy.has_edge_colors());
|
||||
EXPECT_FALSE(copy.has_halfedge_normals());
|
||||
EXPECT_FALSE(copy.has_halfedge_colors());
|
||||
EXPECT_FALSE(copy.has_face_status());
|
||||
EXPECT_FALSE(copy.has_face_normals());
|
||||
EXPECT_FALSE(copy.has_face_colors());
|
||||
EXPECT_FALSE(copy.has_face_texture_index());
|
||||
|
||||
copy.request_vertex_status();
|
||||
copy.request_vertex_normals();
|
||||
copy.request_vertex_colors();
|
||||
copy.request_vertex_texcoords1D();
|
||||
copy.request_vertex_texcoords2D();
|
||||
copy.request_vertex_texcoords3D();
|
||||
copy.request_halfedge_status();
|
||||
copy.request_halfedge_texcoords1D();
|
||||
copy.request_halfedge_texcoords2D();
|
||||
copy.request_halfedge_texcoords3D();
|
||||
copy.request_edge_status();
|
||||
copy.request_edge_colors();
|
||||
copy.request_halfedge_normals();
|
||||
copy.request_halfedge_colors();
|
||||
copy.request_face_status();
|
||||
copy.request_face_normals();
|
||||
copy.request_face_colors();
|
||||
copy.request_face_texture_index();
|
||||
|
||||
EXPECT_TRUE(copy.has_vertex_status()) << "Mesh has no vertex status even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_vertex_normals()) << "Mesh has no vertex normals even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_vertex_colors()) << "Mesh has no vertex colors even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords1D()) << "Mesh has no vertex texcoord1D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords2D()) << "Mesh has no vertex texcoord2D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_vertex_texcoords3D()) << "Mesh has no vertex texcoord3D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_status()) << "Mesh has no halfedge status even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords1D()) << "Mesh has no halfedge texcoords1D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords2D()) << "Mesh has no halfedge texcoords2D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_texcoords3D()) << "Mesh has no halfedge texcoords3D even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_edge_status()) << "Mesh has no edge status even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_edge_colors()) << "Mesh has no edge colors even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_normals()) << "Mesh has no halfedge normals even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_halfedge_colors()) << "Mesh has no halfedge colors even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_face_status()) << "Mesh has no face status even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_face_normals()) << "Mesh has no face normals even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_face_colors()) << "Mesh has no face colors even though they have been requested";
|
||||
EXPECT_TRUE(copy.has_face_texture_index()) << "Mesh has no face texture index even though they have been requested";
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//#define ENABLE_PROPERTY_TIMING_OUTPUT
|
||||
#ifdef ENABLE_PROPERTY_TIMING_OUTPUT
|
||||
#define N_VERTICES_TIMING 1000000
|
||||
#define TIMING_OUTPUT(X) X
|
||||
#else
|
||||
#define N_VERTICES_TIMING 10
|
||||
#define TIMING_OUTPUT(X)
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenMeshPropertyManager : public OpenMeshBase {
|
||||
@@ -62,7 +71,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
|
||||
{
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool");
|
||||
OpenMesh::VPropHandleT<bool>> pm_v_bool(mesh_, "pm_v_bool");
|
||||
pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
ASSERT_FALSE(pm_v_bool[vhandle[i]]);
|
||||
@@ -71,7 +80,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_v_bool[vhandle[i]]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool");
|
||||
OpenMesh::EPropHandleT<bool>> pm_e_bool(mesh_, "pm_e_bool");
|
||||
pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false);
|
||||
for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
|
||||
e_it != f_end; ++e_it)
|
||||
@@ -82,7 +91,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_e_bool[*e_it]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool");
|
||||
OpenMesh::FPropHandleT<bool>> pm_f_bool(mesh_, "pm_f_bool");
|
||||
pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false);
|
||||
for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
|
||||
f_it != f_end; ++f_it)
|
||||
@@ -93,13 +102,12 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_f_bool[*f_it]);
|
||||
}
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
/*
|
||||
* Same thing again, this time with C++11 ranges.
|
||||
*/
|
||||
{
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool2");
|
||||
OpenMesh::VPropHandleT<bool>> pm_v_bool(mesh_, "pm_v_bool2");
|
||||
pm_v_bool.set_range(mesh_.vertices(), false);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
ASSERT_FALSE(pm_v_bool[vhandle[i]]);
|
||||
@@ -108,7 +116,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_v_bool[vhandle[i]]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool2");
|
||||
OpenMesh::EPropHandleT<bool>> pm_e_bool(mesh_, "pm_e_bool2");
|
||||
pm_e_bool.set_range(mesh_.edges(), false);
|
||||
for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
|
||||
e_it != f_end; ++e_it)
|
||||
@@ -119,7 +127,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_e_bool[*e_it]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool2");
|
||||
OpenMesh::FPropHandleT<bool>> pm_f_bool(mesh_, "pm_f_bool2");
|
||||
pm_f_bool.set_range(mesh_.faces(), false);
|
||||
for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
|
||||
f_it != f_end; ++f_it)
|
||||
@@ -129,64 +137,6 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
f_it != f_end; ++f_it)
|
||||
ASSERT_TRUE(pm_f_bool[*f_it]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* C++11 Specific Tests
|
||||
* ====================================================================
|
||||
*/
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
|
||||
template<typename PropHandle, typename Mesh>
|
||||
bool has_property(const Mesh& _mesh, const std::string& _name) {
|
||||
auto dummy_handle = PropHandle{};
|
||||
return _mesh.get_property_handle(dummy_handle, _name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Temporary property
|
||||
*/
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_temp_property) {
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
|
||||
{
|
||||
auto vprop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
|
||||
static_cast<void>(vprop); // Unused variable
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
}
|
||||
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Two temporary properties on a mesh using the same name and type. The second
|
||||
* (inner) one shadows the first (outer) one instead of aliasing.
|
||||
*/
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
|
||||
auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
|
||||
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
|
||||
auto outer_prop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
|
||||
outer_prop[vh] = 100;
|
||||
ASSERT_EQ(100, outer_prop[vh]);
|
||||
|
||||
{
|
||||
// inner_prop uses same type and name as outer_prop
|
||||
auto inner_prop = OpenMesh::makePropertyManagerFromNew<handle_type>(mesh_, prop_name);
|
||||
inner_prop[vh] = 200;
|
||||
ASSERT_EQ(200, inner_prop[vh]);
|
||||
// End of scope: inner_prop is removed from mesh_
|
||||
}
|
||||
|
||||
// Ensure outer_prop still exists and its data has not been overwritten by inner_prop
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_EQ(100, outer_prop[vh]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -199,45 +149,726 @@ TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
|
||||
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_FALSE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
auto prop = OpenMesh::makePropertyManagerFromExistingOrNew<handle_type>(mesh_, prop_name);
|
||||
auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
prop[vh] = 100;
|
||||
// End of scope, property persists
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Since a property of the same name and type already exists, this refers to the existing property.
|
||||
auto prop = OpenMesh::makePropertyManagerFromExistingOrNew<handle_type>(mesh_, prop_name);
|
||||
auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
ASSERT_EQ(100, prop[vh]);
|
||||
prop[vh] = 200;
|
||||
// End of scope, property persists
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Acquire non-owning handle to the property, knowing it exists
|
||||
auto prop = OpenMesh::makePropertyManagerFromExisting<handle_type>(mesh_, prop_name);
|
||||
auto prop = OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
ASSERT_EQ(200, prop[vh]);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Attempt to acquire non-owning handle for a non-existing property
|
||||
ASSERT_THROW(OpenMesh::makePropertyManagerFromExisting<handle_type>(mesh_, "wrong_property_name"), std::runtime_error);
|
||||
auto code_that_throws = [&](){
|
||||
OpenMesh::getProperty<OpenMesh::VertexHandle, int>(mesh_, "wrong_prop_name");
|
||||
};
|
||||
ASSERT_THROW(code_that_throws(), std::runtime_error);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copy_construction) {
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto prop2 = prop1; // prop1 and prop2 should be two different properties with the same content
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
}
|
||||
|
||||
// named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto prop2 = prop1; // prop1 and prop2 should refere to the same property
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_move_construction) {
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
auto prop2 = std::move(prop1);
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
}
|
||||
|
||||
// named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
auto prop2 = std::move(prop1); // prop1 and prop2 should refere to the same property
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "property is not valid anymore";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "did not copy property correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
||||
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(3, mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, mesh_);
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 3) << "Property not initialized correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, mesh_, "ids");
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1; // this should be a no op
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
{
|
||||
auto prop1 = OpenMesh::MProp<int>(mesh_);
|
||||
*prop1 = 43;
|
||||
auto prop2 = prop1;
|
||||
|
||||
prop2 = prop1;
|
||||
|
||||
prop2 = std::move(prop1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
||||
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1); // this should be cheap
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1);
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(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
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(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
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1); // this should be a no op
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
||||
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
auto copy = mesh_;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
copy.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(3, mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, copy);
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 3) << "Property not initialized correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_NO_FATAL_FAILURE(prop2[OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) << "Property not correctly resized";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, copy, "ids");
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(copy, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1;
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = prop1; // this should be a no op
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
auto prop4 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
EXPECT_EQ(prop4[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
||||
|
||||
for (int i = 0; i < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
auto copy = mesh_;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
copy.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1); // this should be cheap
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_NO_FATAL_FAILURE(prop2[OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) << "Property not correctly resized";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1);
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(copy, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
TIMING_OUTPUT(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
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
TIMING_OUTPUT(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
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
|
||||
auto prop6 = OpenMesh::Prop<OpenMesh::VertexHandle, int>(mesh_);
|
||||
prop6 = prop1;
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
prop2 = std::move(prop1); // should copy
|
||||
TIMING_OUTPUT(auto t_end = std::chrono::high_resolution_clock::now();)
|
||||
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_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
auto prop4 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
EXPECT_EQ(prop4[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
TIMING_OUTPUT(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();
|
||||
|
||||
TIMING_OUTPUT(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 < N_VERTICES_TIMING; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
TIMING_OUTPUT(auto t_start = std::chrono::high_resolution_clock::now();)
|
||||
auto id_p = get_id_prop(mesh_);
|
||||
TIMING_OUTPUT(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -325,9 +325,16 @@ TEST_F(OpenMeshReadWriteOBJ, LoadObjWithMaterial) {
|
||||
|
||||
EXPECT_TRUE(fh.is_valid()) << "fh should be valid";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(128/255.0, mesh_.color(fh)[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(128/255.0, mesh_.color(fh)[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(128/255.0, mesh_.color(fh)[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(fh)[3] ) << "Wrong vertex color at vertex 0 component 3";
|
||||
#else
|
||||
EXPECT_EQ(128, mesh_.color(fh)[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(128, mesh_.color(fh)[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(128, mesh_.color(fh)[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
#endif
|
||||
|
||||
mesh_.release_face_colors();
|
||||
}
|
||||
@@ -385,6 +392,24 @@ TEST_F(OpenMeshReadWriteOBJ, LoadSimpleOBJWithVertexColorsAfterVertices) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
@@ -400,6 +425,7 @@ TEST_F(OpenMeshReadWriteOBJ, LoadSimpleOBJWithVertexColorsAfterVertices) {
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
mesh_.release_vertex_colors();
|
||||
}
|
||||
@@ -424,6 +450,23 @@ TEST_F(OpenMeshReadWriteOBJ, LoadSimpleOBJWithVertexColorsAsVCLines) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
@@ -439,6 +482,7 @@ TEST_F(OpenMeshReadWriteOBJ, LoadSimpleOBJWithVertexColorsAsVCLines) {
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
mesh_.release_vertex_colors();
|
||||
|
||||
@@ -499,4 +543,88 @@ TEST_F(OpenMeshReadWriteOBJ, ReadWriteReadSimpleOBJ) {
|
||||
EXPECT_EQ(1, mesh2.normal(mesh2.vertex_handle(7))[2] ) << "Wrong vertex normal at vertex 7 component 2";
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshReadWriteOBJ, FaceTexCoordTest) {
|
||||
|
||||
mesh_.clear();
|
||||
mesh_.request_vertex_normals();
|
||||
mesh_.request_halfedge_texcoords2D();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[5];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
|
||||
// Add one face
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
|
||||
Mesh::FaceHandle fh = mesh_.add_face(face_vhandles);
|
||||
|
||||
// 1 --- 2
|
||||
// | /
|
||||
// | /
|
||||
// | /
|
||||
// 0
|
||||
|
||||
mesh_.set_normal(vhandle[0] , Mesh::Normal(1,0,0));
|
||||
mesh_.set_normal(vhandle[1] , Mesh::Normal(0,1,0));
|
||||
mesh_.set_normal(vhandle[2] , Mesh::Normal(0,0,1));
|
||||
|
||||
|
||||
float u = 8.0f;
|
||||
for ( auto he : mesh_.halfedges() ) {
|
||||
|
||||
mesh_.set_texcoord2D(he,Mesh::TexCoord2D(u,u));
|
||||
u += 1.0;
|
||||
}
|
||||
|
||||
|
||||
u = 0.0f;
|
||||
|
||||
for ( auto he : mesh_.fh_range(fh) )
|
||||
{
|
||||
|
||||
mesh_.set_texcoord2D(he,Mesh::TexCoord2D(u,u));
|
||||
u += 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OpenMesh::IO::Options wopt;
|
||||
wopt += OpenMesh::IO::Options::VertexNormal;
|
||||
wopt += OpenMesh::IO::Options::FaceTexCoord;
|
||||
|
||||
bool ok = OpenMesh::IO::write_mesh(mesh_, "OpenMeshReadWriteOBJ_FaceTexCoordTest.obj", wopt);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to write OpenMeshReadWriteOBJ_FaceTexCoordTest.obj";
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
|
||||
OpenMesh::IO::Options ropt;
|
||||
|
||||
ropt += OpenMesh::IO::Options::FaceTexCoord;
|
||||
|
||||
mesh_.request_vertex_normals();
|
||||
mesh_.request_face_normals();
|
||||
mesh_.request_halfedge_texcoords2D();
|
||||
|
||||
ok = OpenMesh::IO::read_mesh(mesh_, "OpenMeshReadWriteOBJ_FaceTexCoordTest.obj", ropt);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to read back OpenMeshReadWriteOBJ_FaceTexCoordTest.obj";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -60,8 +60,13 @@ TEST_F(OpenMeshReadWriteOFF, WriteAndReadVertexColorsToAndFromOFFFile) {
|
||||
mesh_.add_vertex( Mesh::Point(0,1,1) );
|
||||
mesh_.add_vertex( Mesh::Point(1,0,1) );
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
// using the default color type Vec4f from DefaultTraitsDouble in Traits.hh
|
||||
Mesh::Color testColor(255/255.0, 128/255.0, 64/255.0, 1.0);
|
||||
#else
|
||||
// using the default color type Vec3uc from DefaultTraits in Traits.hh
|
||||
Mesh::Color testColor(255, 128, 64);
|
||||
#endif
|
||||
|
||||
// setting colors (different from black)
|
||||
for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit)
|
||||
@@ -71,7 +76,10 @@ TEST_F(OpenMeshReadWriteOFF, WriteAndReadVertexColorsToAndFromOFFFile) {
|
||||
int count = 0;
|
||||
for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
|
||||
Mesh::Color color = mesh_.color(*vit);
|
||||
if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
|
||||
bool wrong_color = false;
|
||||
for (size_t i = 0; i < color.size(); ++i)
|
||||
wrong_color = wrong_color || (color[i] != testColor[i]);
|
||||
if (wrong_color)
|
||||
++ count;
|
||||
}
|
||||
|
||||
@@ -87,7 +95,10 @@ TEST_F(OpenMeshReadWriteOFF, WriteAndReadVertexColorsToAndFromOFFFile) {
|
||||
count = 0;
|
||||
for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
|
||||
Mesh::Color color = mesh_.color(*vit);
|
||||
if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
|
||||
bool wrong_color = false;
|
||||
for (size_t i = 0; i < color.size(); ++i)
|
||||
wrong_color = wrong_color || (color[i] != testColor[i]);
|
||||
if (wrong_color)
|
||||
++ count;
|
||||
}
|
||||
|
||||
@@ -123,21 +134,39 @@ TEST_F(OpenMeshReadWriteOFF, WriteAndReadFloatVertexColorsToAndFromOFFFile) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
|
||||
EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
|
||||
@@ -179,21 +208,39 @@ TEST_F(OpenMeshReadWriteOFF, WriteAndReadBinaryFloatVertexColorsToAndFromOFFFile
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
|
||||
EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
|
||||
|
||||
@@ -72,7 +72,7 @@ TEST_F(OpenMeshReadWriteOM, LoadSimpleOMWithTexCoords) {
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-texCoords.om",options);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to load cube-minimal-texCoords.om";
|
||||
ASSERT_TRUE(ok) << "Unable to load cube-minimal-texCoords.om";
|
||||
|
||||
EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
@@ -118,21 +118,39 @@ TEST_F(OpenMeshReadWriteOM, LoadSimpleOMWithVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -203,9 +221,15 @@ TEST_F(OpenMeshReadWriteOM, WriteTriangleVertexIntegerColor) {
|
||||
Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
|
||||
mesh.add_face(v1,v2,v3);
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
Mesh::Color c1 = Mesh::Color(0,0,123/255.0,1.0),
|
||||
c2 = Mesh::Color(21/255.0,0,0,1.0),
|
||||
c3 = Mesh::Color(0,222/255.0,0,1.0);
|
||||
#else
|
||||
Mesh::Color c1 = Mesh::Color(0,0,123),
|
||||
c2 = Mesh::Color(21,0,0),
|
||||
c3 = Mesh::Color(0,222,0);
|
||||
#endif
|
||||
|
||||
mesh.set_color(v1,c1);
|
||||
mesh.set_color(v2,c2);
|
||||
@@ -234,9 +258,20 @@ TEST_F(OpenMeshReadWriteOM, WriteTriangleVertexIntegerColor) {
|
||||
EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
|
||||
EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
// OM file format does not support writing colors as float. They are stored as unsigned character.
|
||||
// Thus, the values will not be exactly equal.
|
||||
for (size_t i = 0; i < c1.size(); ++i)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(c1[i] , cmpMesh.color(v1)[i]) << "Wrong colors at coordinate " << i << " of vertex 0";
|
||||
EXPECT_FLOAT_EQ(c2[i] , cmpMesh.color(v2)[i]) << "Wrong colors at coordinate " << i << " of vertex 1";
|
||||
EXPECT_FLOAT_EQ(c3[i] , cmpMesh.color(v3)[i]) << "Wrong colors at coordinate " << i << " of vertex 2";
|
||||
}
|
||||
#else
|
||||
EXPECT_EQ(c1 , cmpMesh.color(v1)) << "Wrong colors at vertex 0";
|
||||
EXPECT_EQ(c2 , cmpMesh.color(v2)) << "Wrong colors at vertex 1";
|
||||
EXPECT_EQ(c3 , cmpMesh.color(v3)) << "Wrong colors at vertex 2";
|
||||
#endif
|
||||
|
||||
//clean up
|
||||
cmpMesh.release_vertex_colors();
|
||||
@@ -464,11 +499,11 @@ TEST_F(OpenMeshReadWriteOM, WriteTriangleEdgeIntProperty) {
|
||||
Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
|
||||
Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
|
||||
|
||||
int va1ue1 = 10,
|
||||
int value1 = 10,
|
||||
value2 = 21,
|
||||
value3 = 32;
|
||||
|
||||
mesh.property(prop,e1) = va1ue1;
|
||||
mesh.property(prop,e1) = value1;
|
||||
mesh.property(prop,e2) = value2;
|
||||
mesh.property(prop,e3) = value3;
|
||||
|
||||
@@ -494,7 +529,7 @@ TEST_F(OpenMeshReadWriteOM, WriteTriangleEdgeIntProperty) {
|
||||
EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
|
||||
EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
|
||||
|
||||
EXPECT_EQ(va1ue1 , cmpMesh.property(prop,e1)) << "Wrong property at edge 0";
|
||||
EXPECT_EQ(value1 , cmpMesh.property(prop,e1)) << "Wrong property at edge 0";
|
||||
EXPECT_EQ(value2 , cmpMesh.property(prop,e2)) << "Wrong property at edge 1";
|
||||
EXPECT_EQ(value3 , cmpMesh.property(prop,e3)) << "Wrong property at edge 2";
|
||||
|
||||
@@ -503,6 +538,308 @@ TEST_F(OpenMeshReadWriteOM, WriteTriangleEdgeIntProperty) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with custom property
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteSplitTriangleEdgeIntProperty) {
|
||||
|
||||
Mesh mesh;
|
||||
|
||||
const std::string propName = "EIProp";
|
||||
const std::string filename = std::string("triangle-minimal-")+propName+".om";
|
||||
|
||||
// generate data
|
||||
Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
|
||||
Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
|
||||
Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
|
||||
auto fh0 = mesh.add_face(v1,v2,v3);
|
||||
auto c = mesh.calc_face_centroid(fh0);
|
||||
Mesh::VertexHandle v4 = mesh.add_vertex(c);
|
||||
mesh.split(fh0, v4);
|
||||
|
||||
|
||||
OpenMesh::EPropHandleT<int> prop;
|
||||
mesh.add_property(prop,propName);
|
||||
mesh.property(prop).set_persistent(true);
|
||||
|
||||
Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
|
||||
Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
|
||||
Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
|
||||
Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
|
||||
Mesh::EdgeHandle e5 = Mesh::EdgeHandle(4);
|
||||
Mesh::EdgeHandle e6 = Mesh::EdgeHandle(5);
|
||||
|
||||
int value1 = 10,
|
||||
value2 = 21,
|
||||
value3 = 32,
|
||||
value4 = 43,
|
||||
value5 = 54,
|
||||
value6 = 65;
|
||||
|
||||
mesh.property(prop,e1) = value1;
|
||||
mesh.property(prop,e2) = value2;
|
||||
mesh.property(prop,e3) = value3;
|
||||
mesh.property(prop,e4) = value4;
|
||||
mesh.property(prop,e5) = value5;
|
||||
mesh.property(prop,e6) = value6;
|
||||
|
||||
// save
|
||||
OpenMesh::IO::Options options;
|
||||
bool ok = OpenMesh::IO::write_mesh(mesh,filename);
|
||||
EXPECT_TRUE(ok) << "Unable to write "<<filename;
|
||||
|
||||
// load
|
||||
Mesh cmpMesh;
|
||||
|
||||
cmpMesh.add_property(prop,propName);
|
||||
cmpMesh.property(prop).set_persistent(true);
|
||||
|
||||
ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
|
||||
EXPECT_TRUE(ok) << "Unable to read "<<filename;
|
||||
|
||||
// compare
|
||||
EXPECT_EQ(4u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(6u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(3u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
|
||||
EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
|
||||
EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
// TODO: should it be possible to read and write double precision exactly?
|
||||
EXPECT_FLOAT_EQ(c[0] , cmpMesh.point(v4)[0]) << "Wrong coordinate 0 at vertex 4";
|
||||
EXPECT_FLOAT_EQ(c[1] , cmpMesh.point(v4)[1]) << "Wrong coordinate 1 at vertex 4";
|
||||
EXPECT_FLOAT_EQ(c[2] , cmpMesh.point(v4)[2]) << "Wrong coordinate 2 at vertex 4";
|
||||
#else
|
||||
EXPECT_EQ(c , cmpMesh.point(v4)) << "Wrong coordinates at vertex 4";
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(value1 , cmpMesh.property(prop,e1)) << "Wrong property at edge 0";
|
||||
EXPECT_EQ(value2 , cmpMesh.property(prop,e2)) << "Wrong property at edge 1";
|
||||
EXPECT_EQ(value3 , cmpMesh.property(prop,e3)) << "Wrong property at edge 2";
|
||||
EXPECT_EQ(value4 , cmpMesh.property(prop,e4)) << "Wrong property at edge 3";
|
||||
EXPECT_EQ(value5 , cmpMesh.property(prop,e5)) << "Wrong property at edge 4";
|
||||
EXPECT_EQ(value6 , cmpMesh.property(prop,e6)) << "Wrong property at edge 5";
|
||||
// The above only shows that the edge properties are stored in the same order which is not what we want if the edges are different
|
||||
|
||||
// Check edge properties based on edges defined by from and to vertex
|
||||
for (auto eh : mesh.edges())
|
||||
{
|
||||
auto heh = mesh.halfedge_handle(eh, 0);
|
||||
auto from_vh = mesh.from_vertex_handle(heh);
|
||||
auto to_vh = mesh.to_vertex_handle(heh);
|
||||
|
||||
// find corresponding halfedge in loaded mesh
|
||||
auto cmpHeh = cmpMesh.find_halfedge(from_vh, to_vh);
|
||||
auto cmpEh = cmpMesh.edge_handle(cmpHeh);
|
||||
|
||||
EXPECT_EQ(mesh.property(prop, eh), cmpMesh.property(prop, cmpEh)) << "Wrong property at input edge " << eh.idx()
|
||||
<< " corresponding to edge " << cmpEh.idx() << " in the loaded Mesh";
|
||||
}
|
||||
|
||||
|
||||
|
||||
// cleanup
|
||||
remove(filename.c_str());
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with status property
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteSplitTriangleStatusProperties) {
|
||||
|
||||
Mesh mesh;
|
||||
|
||||
mesh.request_vertex_status();
|
||||
mesh.request_edge_status();
|
||||
mesh.request_halfedge_status();
|
||||
mesh.request_face_status();
|
||||
|
||||
const std::string filename = std::string("triangle-minimal-status.om");
|
||||
|
||||
// generate data
|
||||
Mesh::VertexHandle v0 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
|
||||
Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
|
||||
Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
|
||||
auto fh0 = mesh.add_face(v0,v1,v2);
|
||||
auto c = mesh.calc_face_centroid(fh0);
|
||||
Mesh::VertexHandle v3 = mesh.add_vertex(c);
|
||||
mesh.split(fh0, v3);
|
||||
|
||||
mesh.delete_vertex(v0);
|
||||
mesh.status(v1).set_selected(true);
|
||||
mesh.status(v2).set_feature(true);
|
||||
mesh.status(v3).set_tagged(true);
|
||||
mesh.status(v2).set_tagged2(true);
|
||||
|
||||
std::vector<bool> vertex_deleted;
|
||||
std::vector<bool> vertex_selected;
|
||||
std::vector<bool> vertex_feature;
|
||||
std::vector<bool> vertex_tagged;
|
||||
std::vector<bool> vertex_tagged2;
|
||||
|
||||
for (auto vh : mesh.all_vertices())
|
||||
{
|
||||
vertex_deleted.push_back(mesh.status(vh).deleted());
|
||||
vertex_selected.push_back(mesh.status(vh).selected());
|
||||
vertex_feature.push_back(mesh.status(vh).feature());
|
||||
vertex_tagged.push_back(mesh.status(vh).tagged());
|
||||
vertex_tagged2.push_back(mesh.status(vh).tagged2());
|
||||
}
|
||||
|
||||
Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
|
||||
Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
|
||||
Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
|
||||
Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
|
||||
|
||||
mesh.status(e1).set_selected(true);
|
||||
mesh.status(e2).set_feature(true);
|
||||
mesh.status(e3).set_tagged(true);
|
||||
mesh.status(e4).set_tagged2(true);
|
||||
|
||||
std::vector<bool> edge_deleted;
|
||||
std::vector<bool> edge_selected;
|
||||
std::vector<bool> edge_feature;
|
||||
std::vector<bool> edge_tagged;
|
||||
std::vector<bool> edge_tagged2;
|
||||
|
||||
for (auto eh : mesh.all_edges())
|
||||
{
|
||||
edge_deleted.push_back(mesh.status(eh).deleted());
|
||||
edge_selected.push_back(mesh.status(eh).selected());
|
||||
edge_feature.push_back(mesh.status(eh).feature());
|
||||
edge_tagged.push_back(mesh.status(eh).tagged());
|
||||
edge_tagged2.push_back(mesh.status(eh).tagged2());
|
||||
}
|
||||
|
||||
|
||||
Mesh::HalfedgeHandle he1 = Mesh::HalfedgeHandle(0);
|
||||
Mesh::HalfedgeHandle he2 = Mesh::HalfedgeHandle(3);
|
||||
Mesh::HalfedgeHandle he3 = Mesh::HalfedgeHandle(5);
|
||||
Mesh::HalfedgeHandle he4 = Mesh::HalfedgeHandle(1);
|
||||
|
||||
mesh.status(he1).set_selected(true);
|
||||
mesh.status(he2).set_feature(true);
|
||||
mesh.status(he3).set_tagged(true);
|
||||
mesh.status(he4).set_tagged2(true);
|
||||
|
||||
std::vector<bool> halfedge_deleted;
|
||||
std::vector<bool> halfedge_selected;
|
||||
std::vector<bool> halfedge_feature;
|
||||
std::vector<bool> halfedge_tagged;
|
||||
std::vector<bool> halfedge_tagged2;
|
||||
|
||||
for (auto heh : mesh.all_halfedges())
|
||||
{
|
||||
halfedge_deleted.push_back(mesh.status(heh).deleted());
|
||||
halfedge_selected.push_back(mesh.status(heh).selected());
|
||||
halfedge_feature.push_back(mesh.status(heh).feature());
|
||||
halfedge_tagged.push_back(mesh.status(heh).tagged());
|
||||
halfedge_tagged2.push_back(mesh.status(heh).tagged2());
|
||||
}
|
||||
|
||||
Mesh::FaceHandle f1 = Mesh::FaceHandle(0);
|
||||
Mesh::FaceHandle f2 = Mesh::FaceHandle(2);
|
||||
Mesh::FaceHandle f3 = Mesh::FaceHandle(1);
|
||||
Mesh::FaceHandle f4 = Mesh::FaceHandle(2);
|
||||
|
||||
mesh.status(f1).set_selected(true);
|
||||
mesh.status(f2).set_feature(true);
|
||||
mesh.status(f3).set_tagged(true);
|
||||
mesh.status(f4).set_tagged2(true);
|
||||
|
||||
std::vector<bool> face_deleted;
|
||||
std::vector<bool> face_selected;
|
||||
std::vector<bool> face_feature;
|
||||
std::vector<bool> face_tagged;
|
||||
std::vector<bool> face_tagged2;
|
||||
|
||||
for (auto fh : mesh.all_faces())
|
||||
{
|
||||
face_deleted.push_back(mesh.status(fh).deleted());
|
||||
face_selected.push_back(mesh.status(fh).selected());
|
||||
face_feature.push_back(mesh.status(fh).feature());
|
||||
face_tagged.push_back(mesh.status(fh).tagged());
|
||||
face_tagged2.push_back(mesh.status(fh).tagged2());
|
||||
}
|
||||
|
||||
// save
|
||||
OpenMesh::IO::Options options = OpenMesh::IO::Options::Status;
|
||||
bool ok = OpenMesh::IO::write_mesh(mesh,filename, options);
|
||||
EXPECT_TRUE(ok) << "Unable to write "<<filename;
|
||||
|
||||
// load
|
||||
Mesh cmpMesh;
|
||||
|
||||
cmpMesh.request_vertex_status();
|
||||
cmpMesh.request_edge_status();
|
||||
cmpMesh.request_halfedge_status();
|
||||
cmpMesh.request_face_status();
|
||||
|
||||
ok = OpenMesh::IO::read_mesh(cmpMesh,filename, options);
|
||||
EXPECT_TRUE(ok) << "Unable to read "<<filename;
|
||||
|
||||
// compare
|
||||
EXPECT_EQ(4u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(6u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(3u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v0)) << "Wrong coordinates at vertex 0";
|
||||
EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 1";
|
||||
EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 2";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
// TODO: should it be possible to read and write double precision exactly?
|
||||
EXPECT_FLOAT_EQ(c[0] , cmpMesh.point(v3)[0]) << "Wrong coordinate 0 at vertex 3";
|
||||
EXPECT_FLOAT_EQ(c[1] , cmpMesh.point(v3)[1]) << "Wrong coordinate 1 at vertex 3";
|
||||
EXPECT_FLOAT_EQ(c[2] , cmpMesh.point(v3)[2]) << "Wrong coordinate 2 at vertex 3";
|
||||
#else
|
||||
EXPECT_EQ(c , cmpMesh.point(v3)) << "Wrong coordinates at vertex 3";
|
||||
#endif
|
||||
|
||||
for (auto vh : cmpMesh.all_vertices())
|
||||
{
|
||||
EXPECT_EQ(cmpMesh.status(vh).deleted(), vertex_deleted [vh.idx()]) << "Wrong deleted status at vertex " << vh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(vh).selected(), vertex_selected[vh.idx()]) << "Wrong selected status at vertex " << vh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(vh).feature(), vertex_feature [vh.idx()]) << "Wrong feature status at vertex " << vh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(vh).tagged(), vertex_tagged [vh.idx()]) << "Wrong tagged status at vertex " << vh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(vh).tagged2(), vertex_tagged2 [vh.idx()]) << "Wrong tagged2 status at vertex " << vh.idx();
|
||||
}
|
||||
|
||||
for (auto eh : cmpMesh.all_edges())
|
||||
{
|
||||
EXPECT_EQ(cmpMesh.status(eh).deleted(), edge_deleted [eh.idx()]) << "Wrong deleted status at edge " << eh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(eh).selected(), edge_selected[eh.idx()]) << "Wrong selected status at edge " << eh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(eh).feature(), edge_feature [eh.idx()]) << "Wrong feature status at edge " << eh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(eh).tagged(), edge_tagged [eh.idx()]) << "Wrong tagged status at edge " << eh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(eh).tagged2(), edge_tagged2 [eh.idx()]) << "Wrong tagged2 status at edge " << eh.idx();
|
||||
}
|
||||
|
||||
for (auto heh : cmpMesh.all_halfedges())
|
||||
{
|
||||
EXPECT_EQ(cmpMesh.status(heh).deleted(), halfedge_deleted [heh.idx()]) << "Wrong deleted status at halfedge " << heh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(heh).selected(), halfedge_selected[heh.idx()]) << "Wrong selected status at halfedge " << heh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(heh).feature(), halfedge_feature [heh.idx()]) << "Wrong feature status at halfedge " << heh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(heh).tagged(), halfedge_tagged [heh.idx()]) << "Wrong tagged status at halfedge " << heh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(heh).tagged2(), halfedge_tagged2 [heh.idx()]) << "Wrong tagged2 status at halfedge " << heh.idx();
|
||||
}
|
||||
|
||||
for (auto fh : cmpMesh.all_faces())
|
||||
{
|
||||
EXPECT_EQ(cmpMesh.status(fh).deleted(), face_deleted [fh.idx()]) << "Wrong deleted status at face " << fh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(fh).selected(), face_selected[fh.idx()]) << "Wrong selected status at face " << fh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(fh).feature(), face_feature [fh.idx()]) << "Wrong feature status at face " << fh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(fh).tagged(), face_tagged [fh.idx()]) << "Wrong tagged status at face " << fh.idx();
|
||||
EXPECT_EQ(cmpMesh.status(fh).tagged2(), face_tagged2 [fh.idx()]) << "Wrong tagged2 status at face " << fh.idx();
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
remove(filename.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with custom property
|
||||
*/
|
||||
@@ -670,4 +1007,506 @@ TEST_F(OpenMeshReadWriteOM, ReadBigMeshWithCustomProperty) {
|
||||
EXPECT_FALSE(wrong) << "min one vertex has worng vertex property";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with vertex status
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyVertexOnly) {
|
||||
|
||||
//read file
|
||||
Mesh mesh;
|
||||
auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
|
||||
auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
|
||||
auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
|
||||
mesh.add_face(vh0, vh1, vh2);
|
||||
|
||||
mesh.request_vertex_status();
|
||||
|
||||
mesh.status(vh0).set_selected(true);
|
||||
mesh.status(vh1).set_feature(true);
|
||||
mesh.status(vh2).set_tagged(true);
|
||||
mesh.status(vh0).set_locked(true);
|
||||
mesh.status(vh1).set_deleted(true);
|
||||
mesh.status(vh2).set_hidden(true);
|
||||
mesh.status(vh0).set_fixed_nonmanifold(true);
|
||||
|
||||
|
||||
std::string filename_without_status = "no_vertex_status_test.om";
|
||||
std::string filename_with_status = "vertex_status_test.om";
|
||||
|
||||
OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
|
||||
OpenMesh::IO::write_mesh(mesh, filename_without_status);
|
||||
OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
}
|
||||
|
||||
// Load status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
|
||||
|
||||
EXPECT_TRUE (loaded_mesh.has_vertex_status()) << "Mesh has no vertex status even though they should have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
if (loaded_mesh.has_vertex_status())
|
||||
{
|
||||
for (auto vh : mesh.vertices())
|
||||
{
|
||||
EXPECT_EQ(mesh.status(vh).bits(), loaded_mesh.status(vh).bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
loaded_mesh.request_vertex_status();
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_TRUE (loaded_mesh.has_vertex_status()) << "Mesh vertex status was removed by reading";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
for (auto vh : loaded_mesh.vertices())
|
||||
{
|
||||
EXPECT_EQ(loaded_mesh.status(vh).bits(), 0u) << "Vertex status was modified even though it should not have been loaded";
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load status from file without status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with halfedge status
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyHalfedgeOnly) {
|
||||
|
||||
//read file
|
||||
Mesh mesh;
|
||||
auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
|
||||
auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
|
||||
auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
|
||||
mesh.add_face(vh0, vh1, vh2);
|
||||
|
||||
mesh.request_halfedge_status();
|
||||
|
||||
auto heh0 = OpenMesh::HalfedgeHandle(0);
|
||||
auto heh1 = OpenMesh::HalfedgeHandle(1);
|
||||
auto heh2 = OpenMesh::HalfedgeHandle(2);
|
||||
auto heh3 = OpenMesh::HalfedgeHandle(3);
|
||||
auto heh4 = OpenMesh::HalfedgeHandle(4);
|
||||
auto heh5 = OpenMesh::HalfedgeHandle(5);
|
||||
|
||||
mesh.status(heh0).set_selected(true);
|
||||
mesh.status(heh1).set_feature(true);
|
||||
mesh.status(heh2).set_tagged(true);
|
||||
mesh.status(heh3).set_locked(true);
|
||||
mesh.status(heh4).set_deleted(true);
|
||||
mesh.status(heh5).set_hidden(true);
|
||||
mesh.status(heh0).set_fixed_nonmanifold(true);
|
||||
|
||||
std::string filename_without_status = "no_halfedge_status_test.om";
|
||||
std::string filename_with_status = "edge_halfstatus_test.om";
|
||||
|
||||
OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
|
||||
OpenMesh::IO::write_mesh(mesh, filename_without_status);
|
||||
OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
}
|
||||
|
||||
// Load status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
|
||||
EXPECT_TRUE(loaded_mesh.has_halfedge_status()) << "Mesh has no halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
if (loaded_mesh.has_halfedge_status())
|
||||
{
|
||||
for (auto heh : mesh.halfedges())
|
||||
{
|
||||
EXPECT_EQ(mesh.status(heh).bits(), loaded_mesh.status(heh).bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
loaded_mesh.request_halfedge_status();
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_TRUE (loaded_mesh.has_halfedge_status()) << "Mesh halfedge status was removed by reading";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
for (auto heh : loaded_mesh.halfedges())
|
||||
{
|
||||
EXPECT_EQ(loaded_mesh.status(heh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load status from file without status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with edge status
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyEdgeOnly) {
|
||||
|
||||
//read file
|
||||
Mesh mesh;
|
||||
auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
|
||||
auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
|
||||
auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
|
||||
mesh.add_face(vh0, vh1, vh2);
|
||||
|
||||
mesh.request_edge_status();
|
||||
|
||||
auto eh0 = OpenMesh::EdgeHandle(0);
|
||||
auto eh1 = OpenMesh::EdgeHandle(1);
|
||||
auto eh2 = OpenMesh::EdgeHandle(2);
|
||||
|
||||
mesh.status(eh0).set_selected(true);
|
||||
mesh.status(eh1).set_feature(true);
|
||||
mesh.status(eh2).set_tagged(true);
|
||||
mesh.status(eh0).set_locked(true);
|
||||
mesh.status(eh1).set_deleted(true);
|
||||
mesh.status(eh2).set_hidden(true);
|
||||
mesh.status(eh0).set_fixed_nonmanifold(true);
|
||||
|
||||
std::string filename_without_status = "no_edge_status_test.om";
|
||||
std::string filename_with_status = "edge_status_test.om";
|
||||
|
||||
OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
|
||||
OpenMesh::IO::write_mesh(mesh, filename_without_status);
|
||||
OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
}
|
||||
|
||||
// Load status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_TRUE(loaded_mesh.has_edge_status()) << "Mesh has no edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
if (loaded_mesh.has_edge_status())
|
||||
{
|
||||
for (auto eh : mesh.edges())
|
||||
{
|
||||
EXPECT_EQ(mesh.status(eh).bits(), loaded_mesh.status(eh).bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
loaded_mesh.request_edge_status();
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_TRUE (loaded_mesh.has_edge_status()) << "Mesh edge status was removed by reading";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
|
||||
for (auto eh : loaded_mesh.edges())
|
||||
{
|
||||
EXPECT_EQ(loaded_mesh.status(eh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load status from file without status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save and load simple mesh with face status
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyFaceOnly) {
|
||||
|
||||
//read file
|
||||
Mesh mesh;
|
||||
auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
|
||||
auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
|
||||
auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
|
||||
auto vh3 = mesh.add_vertex(Mesh::Point(1,1,0));
|
||||
auto fh0 = mesh.add_face(vh0, vh1, vh2);
|
||||
auto fh1 = mesh.add_face(vh2, vh1, vh3);
|
||||
|
||||
mesh.request_face_status();
|
||||
|
||||
mesh.status(fh0).set_selected(true);
|
||||
mesh.status(fh1).set_feature(true);
|
||||
mesh.status(fh0).set_tagged(true);
|
||||
mesh.status(fh1).set_locked(true);
|
||||
mesh.status(fh0).set_deleted(true);
|
||||
mesh.status(fh1).set_hidden(true);
|
||||
mesh.status(fh0).set_fixed_nonmanifold(true);
|
||||
|
||||
std::string filename_without_status = "no_face_status_test.om";
|
||||
std::string filename_with_status = "face_status_test.om";
|
||||
|
||||
OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
|
||||
OpenMesh::IO::write_mesh(mesh, filename_without_status);
|
||||
OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
|
||||
}
|
||||
|
||||
// Load status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
|
||||
EXPECT_TRUE(loaded_mesh.has_face_status()) << "Mesh has no face status even though file should not have a stored status";
|
||||
|
||||
if (loaded_mesh.has_face_status())
|
||||
{
|
||||
for (auto fh : mesh.faces())
|
||||
{
|
||||
EXPECT_EQ(mesh.status(fh).bits(), loaded_mesh.status(fh).bits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load no status from file with status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
loaded_mesh.request_face_status();
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edgestatus even though file should not have a stored status";
|
||||
EXPECT_TRUE (loaded_mesh.has_face_status()) << "Mesh face status was removed by reading";
|
||||
|
||||
for (auto fh : loaded_mesh.faces())
|
||||
{
|
||||
EXPECT_EQ(loaded_mesh.status(fh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load status from file without status
|
||||
{
|
||||
Mesh loaded_mesh;
|
||||
OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
|
||||
|
||||
EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
|
||||
EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Just load a triangle mesh from an om file of version 1.2
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, LoadTriangleMeshVersion_1_2) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
std::string file_name = "cube_tri_version_1_2.om";
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, file_name);
|
||||
|
||||
EXPECT_TRUE(ok) << file_name;
|
||||
|
||||
EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Just load a polyhedral mesh from an om file of version 1.2
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, LoadPolyMeshVersion_1_2) {
|
||||
|
||||
PolyMesh mesh;
|
||||
|
||||
std::string file_name = "cube_poly_version_1_2.om";
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
|
||||
|
||||
EXPECT_TRUE(ok) << file_name;
|
||||
|
||||
EXPECT_EQ(8u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(12u , mesh.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(6u , mesh.n_faces()) << "The number of loaded faces is not correct!";
|
||||
EXPECT_EQ(24u , mesh.n_halfedges()) << "The number of loaded halfedges is not correct!";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Just load a triangle mesh from an om file of version 2.0
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, LoadTriangleMeshVersion_2_0) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
std::string file_name = "cube_tri_version_2_0.om";
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, file_name);
|
||||
|
||||
EXPECT_TRUE(ok) << file_name;
|
||||
|
||||
EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Just load a polyhedral mesh from an om file of version 2.0
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, LoadPolyMeshVersion_2_0) {
|
||||
|
||||
PolyMesh mesh;
|
||||
|
||||
std::string file_name = "cube_poly_version_2_0.om";
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
|
||||
|
||||
EXPECT_TRUE(ok) << file_name;
|
||||
|
||||
EXPECT_EQ(8u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(12u , mesh.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(6u , mesh.n_faces()) << "The number of loaded faces is not correct!";
|
||||
EXPECT_EQ(24u , mesh.n_halfedges()) << "The number of loaded halfedges is not correct!";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to load mesh from om file with a version that is not yet supported
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, LoadTriMeshVersion_7_5) {
|
||||
|
||||
PolyMesh mesh;
|
||||
|
||||
std::string file_name = "cube_tri_version_7_5.om";
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
|
||||
|
||||
EXPECT_FALSE(ok) << file_name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to write and load positions and normals that can only be represented by doubles
|
||||
*/
|
||||
TEST_F(OpenMeshReadWriteOM, WriteAndLoadDoubles) {
|
||||
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<OpenMesh::DefaultTraitsDouble> DoublePolyMesh;
|
||||
|
||||
DoublePolyMesh mesh;
|
||||
mesh.request_vertex_normals();
|
||||
mesh.request_face_normals();
|
||||
|
||||
std::vector<OpenMesh::VertexHandle> vertices;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
vertices.push_back(mesh.add_vertex(DoublePolyMesh::Point(1.0/3.0, std::numeric_limits<double>::min(), std::numeric_limits<double>::max())));
|
||||
mesh.set_normal(vertices.back(), DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits<double>::min(), std::numeric_limits<double>::max()));
|
||||
}
|
||||
auto fh = mesh.add_face(vertices);
|
||||
mesh.set_normal(fh, DoublePolyMesh::Normal(1.0/3.0, std::numeric_limits<double>::min(), std::numeric_limits<double>::max()));
|
||||
|
||||
std::string file_name = "doubles.om";
|
||||
|
||||
OpenMesh::IO::Options opt = OpenMesh::IO::Options::VertexNormal | OpenMesh::IO::Options::FaceNormal;
|
||||
ASSERT_TRUE(OpenMesh::IO::write_mesh(mesh, file_name, opt)) << "Could not write file " << file_name;
|
||||
|
||||
DoublePolyMesh mesh2;
|
||||
mesh2.request_vertex_normals();
|
||||
mesh2.request_face_normals();
|
||||
|
||||
ASSERT_TRUE(OpenMesh::IO::read_mesh(mesh2, file_name, opt)) << "Could not read file " << file_name;
|
||||
|
||||
EXPECT_EQ(mesh.point(OpenMesh::VertexHandle(0)), mesh2.point(OpenMesh::VertexHandle(0)));
|
||||
EXPECT_EQ(mesh.normal(OpenMesh::VertexHandle(0)), mesh2.normal(OpenMesh::VertexHandle(0)));
|
||||
EXPECT_EQ(mesh.normal(OpenMesh::FaceHandle(0)), mesh2.normal(OpenMesh::FaceHandle(0)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,6 +81,24 @@ TEST_F(OpenMeshReadWritePLY, LoadSimplePLY) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a ply ascii file without a newline at the end of the file
|
||||
*
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, LoadSimplePLYNoEndl) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "sphere840.ply");
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to load sphere840.ply";
|
||||
|
||||
EXPECT_EQ(422u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(1260u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(840u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Just load a ply file and set vertex color option before loading
|
||||
*/
|
||||
@@ -129,21 +147,39 @@ TEST_F(OpenMeshReadWritePLY, LoadSimplePLYWithVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -172,21 +208,39 @@ TEST_F(OpenMeshReadWritePLY, LoadPLYFromMeshLabWithVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -224,21 +278,39 @@ TEST_F(OpenMeshReadWritePLY, WriteAndReadBinaryPLYWithVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -276,21 +348,39 @@ TEST_F(OpenMeshReadWritePLY, WriteAndReadPLYWithFloatVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -330,21 +420,39 @@ TEST_F(OpenMeshReadWritePLY, WriteAndReadBinaryPLYWithFloatVertexColors) {
|
||||
EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_FLOAT_EQ(0.0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_FLOAT_EQ(1.0, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#else
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
|
||||
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
|
||||
EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
@@ -525,6 +633,91 @@ TEST_F(OpenMeshReadWritePLY, LoadSimplePLYWithCustomProps) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Just load a ply with custom properties, binary mode
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, LoadSimplePLYWithCustomPropsBinary) {
|
||||
|
||||
PolyMesh mesh;
|
||||
|
||||
OpenMesh::IO::Options options;
|
||||
options += OpenMesh::IO::Options::Custom;
|
||||
options += OpenMesh::IO::Options::Binary;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "cube-minimal-custom_props-binary.ply", options);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to load cube-minimal-custom_props.ply";
|
||||
|
||||
EXPECT_EQ(8u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(12u , mesh.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(6u , mesh.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
OpenMesh::VPropHandleT<float> qualityProp;
|
||||
OpenMesh::VPropHandleT<unsigned int> indexProp;
|
||||
ASSERT_TRUE(mesh.get_property_handle(qualityProp,"quality")) << "Could not access quality property";
|
||||
ASSERT_TRUE(mesh.get_property_handle(indexProp,"index")) << "Could not access index property";
|
||||
|
||||
//check index property
|
||||
for (unsigned i = 0; i < mesh.n_vertices(); ++i)
|
||||
EXPECT_EQ(i ,mesh.property(indexProp,OpenMesh::VertexHandle(i))) << "Vertex index at vertex " << i << " is wrong";
|
||||
|
||||
//check quality property
|
||||
EXPECT_EQ(1.f,mesh.property(qualityProp,OpenMesh::VertexHandle(0))) << "Wrong quality value at Vertex 0";
|
||||
EXPECT_EQ(0.5f,mesh.property(qualityProp,OpenMesh::VertexHandle(1))) << "Wrong quality value at Vertex 1";
|
||||
EXPECT_EQ(0.7f,mesh.property(qualityProp,OpenMesh::VertexHandle(2))) << "Wrong quality value at Vertex 2";
|
||||
EXPECT_EQ(1.f,mesh.property(qualityProp,OpenMesh::VertexHandle(3))) << "Wrong quality value at Vertex 3";
|
||||
EXPECT_EQ(0.1f,mesh.property(qualityProp,OpenMesh::VertexHandle(4))) << "Wrong quality value at Vertex 4";
|
||||
EXPECT_EQ(0.f,mesh.property(qualityProp,OpenMesh::VertexHandle(5))) << "Wrong quality value at Vertex 5";
|
||||
EXPECT_EQ(2.f,mesh.property(qualityProp,OpenMesh::VertexHandle(6))) << "Wrong quality value at Vertex 6";
|
||||
EXPECT_EQ(5.f,mesh.property(qualityProp,OpenMesh::VertexHandle(7))) << "Wrong quality value at Vertex 7";
|
||||
|
||||
//check for custom list properties
|
||||
|
||||
OpenMesh::VPropHandleT< std::vector<int> > testValues;
|
||||
ASSERT_TRUE(mesh.get_property_handle(testValues,"test_values")) << "Could not access texcoords per face";
|
||||
|
||||
EXPECT_EQ(2u,mesh.property(testValues,OpenMesh::VertexHandle(0)).size()) << "Wrong verctor size";
|
||||
|
||||
EXPECT_EQ(1,mesh.property(testValues,OpenMesh::VertexHandle(0))[0]) << "Wrong list value at Vertex 0";
|
||||
EXPECT_EQ(4,mesh.property(testValues,OpenMesh::VertexHandle(1))[1]) << "Wrong list value at Vertex 1";
|
||||
EXPECT_EQ(5,mesh.property(testValues,OpenMesh::VertexHandle(2))[0]) << "Wrong list value at Vertex 2";
|
||||
EXPECT_EQ(8,mesh.property(testValues,OpenMesh::VertexHandle(3))[1]) << "Wrong list value at Vertex 3";
|
||||
EXPECT_EQ(9,mesh.property(testValues,OpenMesh::VertexHandle(4))[0]) << "Wrong list value at Vertex 4";
|
||||
EXPECT_EQ(12,mesh.property(testValues,OpenMesh::VertexHandle(5))[1]) << "Wrong list value at Vertex 5";
|
||||
EXPECT_EQ(13,mesh.property(testValues,OpenMesh::VertexHandle(6))[0]) << "Wrong list value at Vertex 6";
|
||||
EXPECT_EQ(16,mesh.property(testValues,OpenMesh::VertexHandle(7))[1]) << "Wrong list value at Vertex 7";
|
||||
|
||||
OpenMesh::FPropHandleT< std::vector<float> > texCoordsPerFace;
|
||||
ASSERT_TRUE(mesh.get_property_handle(texCoordsPerFace,"texcoords")) << "Could not access texcoords per face";
|
||||
|
||||
for (Mesh::FaceIter f_iter = mesh.faces_begin(); f_iter != mesh.faces_end(); ++f_iter)
|
||||
{
|
||||
EXPECT_EQ(8u, mesh.property(texCoordsPerFace, *f_iter).size()) << "Texcoords per face container has wrong size on face: " << f_iter->idx();
|
||||
if (!mesh.property(texCoordsPerFace, *f_iter).empty())
|
||||
{
|
||||
EXPECT_EQ(1.0, mesh.property(texCoordsPerFace, *f_iter)[0]) << "Texcoords wrong on index 0 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(1.0, mesh.property(texCoordsPerFace, *f_iter)[1]) << "Texcoords wrong on index 1 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(-1.0f, mesh.property(texCoordsPerFace, *f_iter)[2]) << "Texcoords wrong on index 2 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(-1.0f, mesh.property(texCoordsPerFace, *f_iter)[3]) << "Texcoords wrong on index 3 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(0.0f, mesh.property(texCoordsPerFace, *f_iter)[4]) << "Texcoords wrong on index 4 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(0.0f, mesh.property(texCoordsPerFace, *f_iter)[5]) << "Texcoords wrong on index 5 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(-0.5f, mesh.property(texCoordsPerFace, *f_iter)[6]) << "Texcoords wrong on index 6 with face: " << f_iter->idx();
|
||||
EXPECT_EQ(-0.5f, mesh.property(texCoordsPerFace, *f_iter)[7]) << "Texcoords wrong on index 7 with face: " << f_iter->idx();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OpenMesh::FPropHandleT< unsigned > faceIndex;
|
||||
ASSERT_TRUE(mesh.get_property_handle(faceIndex,"faceIndex")) << "Could not access faceIndex per face";
|
||||
|
||||
EXPECT_EQ(0u,mesh.property(faceIndex,OpenMesh::FaceHandle(0))) << "Wrong index value at FaceHandle 0";
|
||||
EXPECT_EQ(1u,mesh.property(faceIndex,OpenMesh::FaceHandle(1))) << "Wrong index value at FaceHandle 1";
|
||||
EXPECT_EQ(2u,mesh.property(faceIndex,OpenMesh::FaceHandle(2))) << "Wrong index value at FaceHandle 2";
|
||||
EXPECT_EQ(3u,mesh.property(faceIndex,OpenMesh::FaceHandle(3))) << "Wrong index value at FaceHandle 3";
|
||||
EXPECT_EQ(4u,mesh.property(faceIndex,OpenMesh::FaceHandle(4))) << "Wrong index value at FaceHandle 4";
|
||||
EXPECT_EQ(5u,mesh.property(faceIndex,OpenMesh::FaceHandle(5))) << "Wrong index value at FaceHandle 5";
|
||||
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshReadWritePLY, WriteReadSimplePLYWithCustomProps) {
|
||||
|
||||
@@ -728,4 +921,233 @@ TEST_F(OpenMeshReadWritePLY, LoadSimpleBinaryPLYWithExtraElements) {
|
||||
EXPECT_EQ(12u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore a file that does not contain vertices and faces
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, IgnoreNonMeshPlyFile) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
std::stringstream data;
|
||||
data << "ply" << "\n";
|
||||
data << "format binary_little_endian 1.0" << "\n";
|
||||
data << "comment Image data" << "\n";
|
||||
data << "element image 0" << "\n";
|
||||
data << "property list uint16 uint16 row" << "\n";
|
||||
data << "end_header" << "\n";
|
||||
|
||||
OpenMesh::IO::Options options = OpenMesh::IO::Options::Binary;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, data, ".ply", options);
|
||||
|
||||
EXPECT_TRUE(ok) << "This empty file should be readable without an error!";
|
||||
|
||||
EXPECT_EQ(0u, mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(0u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(0u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ignore a file that does not contain vertices and faces
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, FailOnUnknownPropertyTypeForLists) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
std::stringstream data;
|
||||
data << "ply" << "\n";
|
||||
data << "format binary_little_endian 1.0" << "\n";
|
||||
data << "comment Image data" << "\n";
|
||||
data << "element image 0" << "\n";
|
||||
data << "property list blibb blubb row" << "\n";
|
||||
data << "end_header" << "\n";
|
||||
|
||||
OpenMesh::IO::Options options = OpenMesh::IO::Options::Binary;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, data, ".ply", options);
|
||||
|
||||
EXPECT_FALSE(ok) << "This file should fail to read!";
|
||||
|
||||
EXPECT_EQ(0u, mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(0u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(0u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
}
|
||||
|
||||
/*
|
||||
* Load an ASCII PLY file of a cube with float RGB face colors
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, LoadSimplePLYWithFaceColors) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
mesh_.request_face_colors();
|
||||
|
||||
OpenMesh::IO::Options options;
|
||||
options += OpenMesh::IO::Options::FaceColor;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-faceColors.ply",options);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to load cube-minimal-faceColors.ply";
|
||||
|
||||
EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
|
||||
EXPECT_EQ(18u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
|
||||
EXPECT_EQ(12u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(0))[0] ) << "Wrong face color at face 0";
|
||||
EXPECT_FLOAT_EQ(117/255.0, mesh_.color(mesh_.face_handle(0))[1] ) << "Wrong face color at face 0";
|
||||
EXPECT_FLOAT_EQ(177/255.0, mesh_.color(mesh_.face_handle(0))[2] ) << "Wrong face color at face 0";
|
||||
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(3))[0] ) << "Wrong face color at face 3";
|
||||
EXPECT_FLOAT_EQ(255/255.0, mesh_.color(mesh_.face_handle(3))[1] ) << "Wrong face color at face 3";
|
||||
EXPECT_FLOAT_EQ(135/255.0, mesh_.color(mesh_.face_handle(3))[2] ) << "Wrong face color at face 3";
|
||||
|
||||
EXPECT_FLOAT_EQ(163/255.0, mesh_.color(mesh_.face_handle(4))[0] ) << "Wrong face color at face 4";
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(4))[1] ) << "Wrong face color at face 4";
|
||||
EXPECT_FLOAT_EQ(177/255.0, mesh_.color(mesh_.face_handle(4))[2] ) << "Wrong face color at face 4";
|
||||
|
||||
EXPECT_FLOAT_EQ(255/255.0, mesh_.color(mesh_.face_handle(7))[0] ) << "Wrong face color at face 7";
|
||||
EXPECT_FLOAT_EQ(140/255.0, mesh_.color(mesh_.face_handle(7))[1] ) << "Wrong face color at face 7";
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(7))[2] ) << "Wrong face color at face 7";
|
||||
#else
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(0))[0] ) << "Wrong face color at face 0";
|
||||
EXPECT_EQ(117, mesh_.color(mesh_.face_handle(0))[1] ) << "Wrong face color at face 0";
|
||||
EXPECT_EQ(177, mesh_.color(mesh_.face_handle(0))[2] ) << "Wrong face color at face 0";
|
||||
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(3))[0] ) << "Wrong face color at face 3";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.face_handle(3))[1] ) << "Wrong face color at face 3";
|
||||
EXPECT_EQ(135, mesh_.color(mesh_.face_handle(3))[2] ) << "Wrong face color at face 3";
|
||||
|
||||
EXPECT_EQ(163, mesh_.color(mesh_.face_handle(4))[0] ) << "Wrong face color at face 4";
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(4))[1] ) << "Wrong face color at face 4";
|
||||
EXPECT_EQ(177, mesh_.color(mesh_.face_handle(4))[2] ) << "Wrong face color at face 4";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.face_handle(7))[0] ) << "Wrong face color at face 7";
|
||||
EXPECT_EQ(140, mesh_.color(mesh_.face_handle(7))[1] ) << "Wrong face color at face 7";
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(7))[2] ) << "Wrong face color at face 7";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.vertex_has_color()) << "Wrong user options are returned!";
|
||||
EXPECT_TRUE(options.face_has_color()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.color_has_alpha()) << "Wrong user options are returned!";
|
||||
EXPECT_FALSE(options.is_binary()) << "Wrong user options are returned!";
|
||||
|
||||
mesh_.release_face_colors();
|
||||
}
|
||||
|
||||
/*
|
||||
* Write and read PLY files with face colors in various formats
|
||||
*/
|
||||
TEST_F(OpenMeshReadWritePLY, WriteAndReadPLYWithFaceColors) {
|
||||
struct Format {
|
||||
Format(const char* outFileName, OpenMesh::IO::Options options) :
|
||||
_outFileName(outFileName),
|
||||
_options(options)
|
||||
{}
|
||||
const char* _outFileName;
|
||||
const OpenMesh::IO::Options _options;
|
||||
}
|
||||
formats[] =
|
||||
{
|
||||
Format("cube-minimal-faceColors_ascii_uchar.ply",
|
||||
OpenMesh::IO::Options::Default),
|
||||
Format("cube-minimal-faceColors_ascii_float.ply",
|
||||
OpenMesh::IO::Options::ColorFloat),
|
||||
Format("cube-minimal-faceColors_binary_uchar.ply",
|
||||
OpenMesh::IO::Options::Binary),
|
||||
Format("cube-minimal-faceColors_binary_float.ply",
|
||||
OpenMesh::IO::Options::Binary | OpenMesh::IO::Options::ColorFloat),
|
||||
// Test writing/reading alpha values (all default 1.0/255), but the test mesh
|
||||
// Color type has no alpha channel so there's nothing to test below
|
||||
Format("cube-minimal-faceColors_alpha_ascii_uchar.ply",
|
||||
OpenMesh::IO::Options::ColorAlpha),
|
||||
Format("cube-minimal-faceColors_alpha_ascii_float.ply",
|
||||
OpenMesh::IO::Options::ColorFloat | OpenMesh::IO::Options::ColorAlpha),
|
||||
Format("cube-minimal-faceColors_alpha_binary_uchar.ply",
|
||||
OpenMesh::IO::Options::Binary | OpenMesh::IO::Options::ColorAlpha),
|
||||
Format("cube-minimal-faceColors_alpha_binary_float.ply",
|
||||
OpenMesh::IO::Options::Binary | OpenMesh::IO::Options::ColorFloat | OpenMesh::IO::Options::ColorAlpha),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(formats) / sizeof(Format); ++i)
|
||||
{
|
||||
const char* outFileName = formats[i]._outFileName;
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
mesh_.request_face_colors();
|
||||
|
||||
OpenMesh::IO::Options options;
|
||||
options += OpenMesh::IO::Options::FaceColor;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-faceColors.ply", options);
|
||||
|
||||
EXPECT_TRUE(ok) << "Unable to load cube-minimal-faceColors.ply";
|
||||
|
||||
options = formats[i]._options;
|
||||
options += OpenMesh::IO::Options::FaceColor;
|
||||
ok = OpenMesh::IO::write_mesh(mesh_, outFileName, options);
|
||||
EXPECT_TRUE(ok) << "Unable to write " << outFileName;
|
||||
|
||||
// Reset for reading: let the reader determine binary/float/etc.
|
||||
options = OpenMesh::IO::Options::FaceColor;
|
||||
mesh_.clear();
|
||||
ok = OpenMesh::IO::read_mesh(mesh_, outFileName, options);
|
||||
EXPECT_TRUE(ok) << "Unable to load " << outFileName;
|
||||
|
||||
EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct: " << outFileName;
|
||||
EXPECT_EQ(18u, mesh_.n_edges()) << "The number of loaded edges is not correct: " << outFileName;
|
||||
EXPECT_EQ(12u, mesh_.n_faces()) << "The number of loaded faces is not correct: " << outFileName;
|
||||
|
||||
#ifdef TEST_DOUBLE_TRAITS
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(0))[0] ) << "Wrong face color at face 0";
|
||||
EXPECT_FLOAT_EQ(117/255.0, mesh_.color(mesh_.face_handle(0))[1] ) << "Wrong face color at face 0";
|
||||
EXPECT_FLOAT_EQ(177/255.0, mesh_.color(mesh_.face_handle(0))[2] ) << "Wrong face color at face 0";
|
||||
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(3))[0] ) << "Wrong face color at face 3";
|
||||
EXPECT_FLOAT_EQ(255/255.0, mesh_.color(mesh_.face_handle(3))[1] ) << "Wrong face color at face 3";
|
||||
EXPECT_FLOAT_EQ(135/255.0, mesh_.color(mesh_.face_handle(3))[2] ) << "Wrong face color at face 3";
|
||||
|
||||
EXPECT_FLOAT_EQ(163/255.0, mesh_.color(mesh_.face_handle(4))[0] ) << "Wrong face color at face 4";
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(4))[1] ) << "Wrong face color at face 4";
|
||||
EXPECT_FLOAT_EQ(177/255.0, mesh_.color(mesh_.face_handle(4))[2] ) << "Wrong face color at face 4";
|
||||
|
||||
EXPECT_FLOAT_EQ(255/255.0, mesh_.color(mesh_.face_handle(7))[0] ) << "Wrong face color at face 7";
|
||||
EXPECT_FLOAT_EQ(140/255.0, mesh_.color(mesh_.face_handle(7))[1] ) << "Wrong face color at face 7";
|
||||
EXPECT_FLOAT_EQ(107/255.0, mesh_.color(mesh_.face_handle(7))[2] ) << "Wrong face color at face 7";
|
||||
#else
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(0))[0] ) << "Wrong face color at face 0";
|
||||
EXPECT_EQ(117, mesh_.color(mesh_.face_handle(0))[1] ) << "Wrong face color at face 0";
|
||||
EXPECT_EQ(177, mesh_.color(mesh_.face_handle(0))[2] ) << "Wrong face color at face 0";
|
||||
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(3))[0] ) << "Wrong face color at face 3";
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.face_handle(3))[1] ) << "Wrong face color at face 3";
|
||||
EXPECT_EQ(135, mesh_.color(mesh_.face_handle(3))[2] ) << "Wrong face color at face 3";
|
||||
|
||||
EXPECT_EQ(163, mesh_.color(mesh_.face_handle(4))[0] ) << "Wrong face color at face 4";
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(4))[1] ) << "Wrong face color at face 4";
|
||||
EXPECT_EQ(177, mesh_.color(mesh_.face_handle(4))[2] ) << "Wrong face color at face 4";
|
||||
|
||||
EXPECT_EQ(255, mesh_.color(mesh_.face_handle(7))[0] ) << "Wrong face color at face 7";
|
||||
EXPECT_EQ(140, mesh_.color(mesh_.face_handle(7))[1] ) << "Wrong face color at face 7";
|
||||
EXPECT_EQ(107, mesh_.color(mesh_.face_handle(7))[2] ) << "Wrong face color at face 7";
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned: " << outFileName;
|
||||
EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned: " << outFileName;
|
||||
EXPECT_FALSE(options.vertex_has_color()) << "Wrong user options are returned: " << outFileName;
|
||||
EXPECT_TRUE(options.face_has_color()) << "Wrong user options are returned: " << outFileName;
|
||||
EXPECT_EQ(formats[i]._options.color_is_float(), options.color_is_float()) <<
|
||||
"Wrong user options are returned: " << outFileName;
|
||||
EXPECT_EQ(formats[i]._options.is_binary(), options.is_binary()) <<
|
||||
"Wrong user options are returned: " << outFileName;
|
||||
|
||||
mesh_.release_face_colors();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
566
src/Unittests/unittests_smart_handles.cc
Normal file
566
src/Unittests/unittests_smart_handles.cc
Normal file
@@ -0,0 +1,566 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenMeshSmartHandles : public OpenMeshBase {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[8];
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(-1, 1, -1));
|
||||
|
||||
// Add six faces to form a cube
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
// Test setup:
|
||||
//
|
||||
//
|
||||
// 3 ======== 2
|
||||
// / /|
|
||||
// / / | z
|
||||
// 0 ======== 1 | |
|
||||
// | | | | y
|
||||
// | 7 | 6 | /
|
||||
// | | / | /
|
||||
// | |/ |/
|
||||
// 4 ======== 5 -------> x
|
||||
//
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(18u, mesh_.n_edges() ) << "Wrong number of Edges";
|
||||
EXPECT_EQ(36u, mesh_.n_halfedges() ) << "Wrong number of HalfEdges";
|
||||
EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(12u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
|
||||
mesh_.clear();
|
||||
}
|
||||
|
||||
// Member already defined in OpenMeshBase
|
||||
//Mesh mesh_;
|
||||
};
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Test if navigation operations on smart handles yield the expected element
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, SimpleNavigation)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
EXPECT_EQ(mesh_.halfedge_handle(vh), vh.halfedge()) << "outgoing halfedge of vertex does not match";
|
||||
}
|
||||
|
||||
for (auto heh : mesh_.halfedges())
|
||||
{
|
||||
EXPECT_EQ(mesh_.next_halfedge_handle(heh), heh.next()) << "next halfedge of halfedge does not match";
|
||||
EXPECT_EQ(mesh_.prev_halfedge_handle(heh), heh.prev()) << "prevt halfedge of halfedge does not match";
|
||||
EXPECT_EQ(mesh_.opposite_halfedge_handle(heh), heh.opp()) << "opposite halfedge of halfedge does not match";
|
||||
EXPECT_EQ(mesh_.to_vertex_handle(heh), heh.to()) << "to vertex handle of halfedge does not match";
|
||||
EXPECT_EQ(mesh_.from_vertex_handle(heh), heh.from()) << "from vertex handle of halfedge does not match";
|
||||
EXPECT_EQ(mesh_.face_handle(heh), heh.face()) << "face handle of halfedge does not match";
|
||||
}
|
||||
|
||||
for (auto eh : mesh_.edges())
|
||||
{
|
||||
EXPECT_EQ(mesh_.halfedge_handle(eh, 0), eh.h0()) << "halfedge 0 of edge does not match";
|
||||
EXPECT_EQ(mesh_.halfedge_handle(eh, 1), eh.h1()) << "halfedge 1 of edge does not match";
|
||||
EXPECT_EQ(mesh_.from_vertex_handle(mesh_.halfedge_handle(eh, 0)), eh.v0()) << "first vertex of edge does not match";
|
||||
EXPECT_EQ(mesh_.to_vertex_handle (mesh_.halfedge_handle(eh, 0)), eh.v1()) << "second vertex of edge does not match";
|
||||
}
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
EXPECT_EQ(mesh_.halfedge_handle(fh), fh.halfedge()) << "halfedge of face does not match";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Test if ranges yield the same elements when using smart handles
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, SimpleRanges)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
{
|
||||
std::vector<OpenMesh::VertexHandle> handles0;
|
||||
std::vector<OpenMesh::VertexHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : vh.vertices())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of vertex does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.voh_range(vh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : vh.outgoing_halfedges())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "outgoing halfedge range of vertex does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.vih_range(vh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : vh.incoming_halfedges())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "incoming halfedge range of vertex does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::EdgeHandle> handles0;
|
||||
std::vector<OpenMesh::EdgeHandle> handles1;
|
||||
for (auto h : mesh_.ve_range(vh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : vh.edges())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "edge range of vertex does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::FaceHandle> handles0;
|
||||
std::vector<OpenMesh::FaceHandle> handles1;
|
||||
for (auto h : mesh_.vf_range(vh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : vh.faces())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "face range of vertex does not match";
|
||||
}
|
||||
}
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
{
|
||||
std::vector<OpenMesh::VertexHandle> handles0;
|
||||
std::vector<OpenMesh::VertexHandle> handles1;
|
||||
for (auto h : mesh_.fv_range(fh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : fh.vertices())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of face does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.fh_range(fh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : fh.halfedges())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "halfedge range of face does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::EdgeHandle> handles0;
|
||||
std::vector<OpenMesh::EdgeHandle> handles1;
|
||||
for (auto h : mesh_.fe_range(fh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : fh.edges())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "edge range of face does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::FaceHandle> handles0;
|
||||
std::vector<OpenMesh::FaceHandle> handles1;
|
||||
for (auto h : mesh_.ff_range(fh))
|
||||
handles0.push_back(h);
|
||||
for (auto h : fh.faces())
|
||||
handles1.push_back(h);
|
||||
EXPECT_EQ(handles0, handles1) << "face range of face does not match";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Test if ranges yield the same elements when using smart handles
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, RangesOfRanges)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
{
|
||||
std::vector<OpenMesh::VertexHandle> handles0;
|
||||
std::vector<OpenMesh::VertexHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
for (auto h2 : mesh_.vv_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.vertices())
|
||||
for (auto h2 : h.vertices())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of vertex range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
for (auto h2 : mesh_.voh_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.vertices())
|
||||
for (auto h2 : h.outgoing_halfedges())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "outgoing halfedge range of vertex range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
for (auto h2 : mesh_.vih_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.vertices())
|
||||
for (auto h2 : h.incoming_halfedges())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "incoming halfedge range of vertex range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::EdgeHandle> handles0;
|
||||
std::vector<OpenMesh::EdgeHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
for (auto h2 : mesh_.ve_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.vertices())
|
||||
for (auto h2 : h.edges())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "edge range of vertex range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::FaceHandle> handles0;
|
||||
std::vector<OpenMesh::FaceHandle> handles1;
|
||||
for (auto h : mesh_.vv_range(vh))
|
||||
for (auto h2 : mesh_.vf_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.vertices())
|
||||
for (auto h2 : h.faces())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "face range of vertex range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::VertexHandle> handles0;
|
||||
std::vector<OpenMesh::VertexHandle> handles1;
|
||||
for (auto h : mesh_.vf_range(vh))
|
||||
for (auto h2 : mesh_.fv_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.faces())
|
||||
for (auto h2 : h.vertices())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles0;
|
||||
std::vector<OpenMesh::HalfedgeHandle> handles1;
|
||||
for (auto h : mesh_.vf_range(vh))
|
||||
for (auto h2 : mesh_.fh_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.faces())
|
||||
for (auto h2 : h.halfedges())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
|
||||
}
|
||||
{
|
||||
std::vector<OpenMesh::FaceHandle> handles0;
|
||||
std::vector<OpenMesh::FaceHandle> handles1;
|
||||
for (auto h : mesh_.vf_range(vh))
|
||||
for (auto h2 : mesh_.ff_range(h))
|
||||
handles0.push_back(h2);
|
||||
for (auto h : vh.faces())
|
||||
for (auto h2 : h.faces())
|
||||
handles1.push_back(h2);
|
||||
EXPECT_EQ(handles0, handles1) << "vertex range of face range does not match";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Test a chain of navigation on a cube
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, ComplicatedNavigtaion)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
EXPECT_EQ(mesh_.next_halfedge_handle(
|
||||
mesh_.opposite_halfedge_handle(
|
||||
mesh_.halfedge_handle(vh))),
|
||||
vh.out().opp().next());
|
||||
EXPECT_EQ(mesh_.prev_halfedge_handle(
|
||||
mesh_.prev_halfedge_handle(
|
||||
mesh_.opposite_halfedge_handle(
|
||||
mesh_.next_halfedge_handle(
|
||||
mesh_.next_halfedge_handle(
|
||||
mesh_.halfedge_handle(vh)))))),
|
||||
vh.out().next().next().opp().prev().prev());
|
||||
EXPECT_EQ(mesh_.face_handle(
|
||||
mesh_.opposite_halfedge_handle(
|
||||
mesh_.halfedge_handle(
|
||||
mesh_.face_handle(
|
||||
mesh_.opposite_halfedge_handle(
|
||||
mesh_.next_halfedge_handle(
|
||||
mesh_.halfedge_handle(vh))))))),
|
||||
vh.out().next().opp().face().halfedge().opp().face());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Test performance of smart handles
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, Performance)
|
||||
{
|
||||
#if NDEBUG
|
||||
int n_tests = 10000000;
|
||||
#else
|
||||
int n_tests = 300000;
|
||||
#endif
|
||||
|
||||
auto t_before_old = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::vector<OpenMesh::HalfedgeHandle> halfedges0;
|
||||
for (int i = 0; i < n_tests; ++i)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
auto heh = mesh_.prev_halfedge_handle(
|
||||
mesh_.prev_halfedge_handle(
|
||||
mesh_.opposite_halfedge_handle(
|
||||
mesh_.next_halfedge_handle(
|
||||
mesh_.next_halfedge_handle(
|
||||
mesh_.halfedge_handle(vh))))));
|
||||
if (i == 0)
|
||||
halfedges0.push_back(heh);
|
||||
}
|
||||
}
|
||||
|
||||
auto t_after_old = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::vector<OpenMesh::HalfedgeHandle> halfedges1;
|
||||
for (int i = 0; i < n_tests; ++i)
|
||||
{
|
||||
for (auto vh : mesh_.vertices())
|
||||
{
|
||||
auto heh = vh.out().next().next().opp().prev().prev();
|
||||
if (i == 0)
|
||||
halfedges1.push_back(heh);
|
||||
}
|
||||
}
|
||||
|
||||
auto t_after_new = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << "Conventional navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_old-t_before_old).count() << "ms" << std::endl;
|
||||
std::cout << "SmartHandle navigation took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_after_new-t_after_old ).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(halfedges0, halfedges1) << "halfedges do not match";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Mix old and new api
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, MixOldAndNew)
|
||||
{
|
||||
for (OpenMesh::SmartHalfedgeHandle heh : mesh_.halfedges())
|
||||
{
|
||||
heh = mesh_.opposite_halfedge_handle(heh);
|
||||
EXPECT_TRUE((std::is_same<OpenMesh::SmartEdgeHandle, decltype(OpenMesh::PolyConnectivity::s_edge_handle(heh))>::value));
|
||||
EXPECT_TRUE((std::is_same<OpenMesh::SmartEdgeHandle, decltype(mesh_.edge_handle(heh))>::value));
|
||||
EXPECT_TRUE((std::is_same<OpenMesh::SmartFaceHandle, decltype(mesh_.face_handle(heh))>::value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* comparability
|
||||
*/
|
||||
TEST_F(OpenMeshSmartHandles, ComparisionBetweenSmartHandleAndNormalHandles)
|
||||
{
|
||||
OpenMesh::VertexHandle vh(0);
|
||||
OpenMesh::SmartVertexHandle svh(0, &mesh_);
|
||||
EXPECT_EQ(vh, svh) << "Vertex handle and smart vertex handle are different";
|
||||
|
||||
std::vector<OpenMesh::VertexHandle> vertices = mesh_.vertices().to_vector([](OpenMesh::SmartVertexHandle _svh) { return OpenMesh::VertexHandle(_svh); });
|
||||
|
||||
std::replace(vertices.begin(), vertices.end(), OpenMesh::VertexHandle(0), OpenMesh::VertexHandle(1));
|
||||
EXPECT_EQ(vertices[0], OpenMesh::VertexHandle(1));
|
||||
|
||||
std::vector<OpenMesh::SmartVertexHandle> smart_vertices = mesh_.vertices().to_vector();
|
||||
|
||||
std::replace(smart_vertices.begin(), smart_vertices.end(), OpenMesh::SmartVertexHandle(0, &mesh_), OpenMesh::SmartVertexHandle(1, &mesh_));
|
||||
EXPECT_EQ(smart_vertices[0], OpenMesh::VertexHandle(1));
|
||||
EXPECT_EQ(smart_vertices[0], OpenMesh::SmartVertexHandle(1, &mesh_));
|
||||
|
||||
std::replace(vertices.begin(), vertices.end(), OpenMesh::SmartVertexHandle(1, &mesh_), OpenMesh::SmartVertexHandle(2, &mesh_));
|
||||
EXPECT_EQ(vertices[0], OpenMesh::VertexHandle(2));
|
||||
|
||||
}
|
||||
|
||||
TEST(OpenMeshSmartHandlesNoFixture, AddingFacesPolyMesh)
|
||||
{
|
||||
using MyMesh = OpenMesh::PolyMesh_ArrayKernelT<>;
|
||||
|
||||
MyMesh mesh;
|
||||
|
||||
std::vector<OpenMesh::SmartVertexHandle> vertices;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
vertices.push_back(mesh.add_vertex(MyMesh::Point()));
|
||||
|
||||
auto fh = mesh.add_face(vertices);
|
||||
|
||||
for (auto heh : fh.halfedges())
|
||||
{
|
||||
heh = heh.next();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OpenMeshSmartHandlesNoFixture, AddingFacesTriMesh)
|
||||
{
|
||||
using MyMesh = OpenMesh::TriMesh_ArrayKernelT<>;
|
||||
|
||||
MyMesh mesh;
|
||||
|
||||
std::vector<OpenMesh::SmartVertexHandle> vertices;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
vertices.push_back(mesh.add_vertex(MyMesh::Point()));
|
||||
|
||||
auto fh = mesh.add_face(vertices);
|
||||
|
||||
for (auto heh : fh.halfedges())
|
||||
{
|
||||
heh = heh.next();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OpenMeshSmartHandlesNoFixture, SplitTriMesh)
|
||||
{
|
||||
using MyMesh = OpenMesh::TriMesh_ArrayKernelT<>;
|
||||
|
||||
MyMesh mesh;
|
||||
|
||||
std::vector<OpenMesh::SmartVertexHandle> vertices;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
vertices.push_back(mesh.add_vertex(MyMesh::Point()));
|
||||
|
||||
auto fh = mesh.add_face(vertices);
|
||||
|
||||
auto p = (MyMesh::Point());
|
||||
|
||||
OpenMesh::SmartVertexHandle vh = mesh.split(fh, p);
|
||||
OpenMesh::SmartEdgeHandle eh = fh.halfedge().edge();
|
||||
OpenMesh::SmartVertexHandle vh2 = mesh.split(eh, p);
|
||||
|
||||
EXPECT_NE(vh.idx(), vh2.idx()) << "This was only intended to fix an unused variable warning but cool that it caugth an actual error now";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
391
src/Unittests/unittests_smart_ranges.cc
Normal file
391
src/Unittests/unittests_smart_ranges.cc
Normal file
@@ -0,0 +1,391 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenMeshSmartRanges : public OpenMeshBase {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[8];
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(-1, 1, -1));
|
||||
|
||||
// Add six faces to form a cube
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
//=======================
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
// Test setup:
|
||||
//
|
||||
//
|
||||
// 3 ======== 2
|
||||
// / /|
|
||||
// / / | z
|
||||
// 0 ======== 1 | |
|
||||
// | | | | y
|
||||
// | 7 | 6 | /
|
||||
// | | / | /
|
||||
// | |/ |/
|
||||
// 4 ======== 5 -------> x
|
||||
//
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(18u, mesh_.n_edges() ) << "Wrong number of Edges";
|
||||
EXPECT_EQ(36u, mesh_.n_halfedges() ) << "Wrong number of HalfEdges";
|
||||
EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(12u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
|
||||
mesh_.clear();
|
||||
}
|
||||
|
||||
// Member already defined in OpenMeshBase
|
||||
//Mesh mesh_;
|
||||
};
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
template <typename HandleT>
|
||||
struct F
|
||||
{
|
||||
unsigned int operator()(HandleT ) { return 1; }
|
||||
};
|
||||
|
||||
/* Test if smart ranges work
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, Sum)
|
||||
{
|
||||
auto one = [](OpenMesh::VertexHandle ) { return 1u; };
|
||||
EXPECT_EQ(mesh_.vertices().sum(one), mesh_.n_vertices());
|
||||
EXPECT_EQ(mesh_.vertices().sum(F<OpenMesh::VertexHandle>()), mesh_.n_vertices());
|
||||
EXPECT_EQ(mesh_.halfedges().sum(F<OpenMesh::HalfedgeHandle>()), mesh_.n_halfedges());
|
||||
EXPECT_EQ(mesh_.edges().sum(F<OpenMesh::EdgeHandle>()), mesh_.n_edges());
|
||||
EXPECT_EQ(mesh_.faces().sum(F<OpenMesh::FaceHandle>()), mesh_.n_faces());
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
EXPECT_EQ(vh.vertices().sum(F<OpenMesh::VertexHandle>()), mesh_.valence(vh));
|
||||
for (auto vh : mesh_.vertices())
|
||||
EXPECT_EQ(vh.faces().sum(F<OpenMesh::FaceHandle>()), mesh_.valence(vh));
|
||||
for (auto vh : mesh_.vertices())
|
||||
EXPECT_EQ(vh.outgoing_halfedges().sum(F<OpenMesh::HalfedgeHandle>()), mesh_.valence(vh));
|
||||
for (auto vh : mesh_.vertices())
|
||||
EXPECT_EQ(vh.incoming_halfedges().sum(F<OpenMesh::HalfedgeHandle>()), mesh_.valence(vh));
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
EXPECT_EQ(fh.vertices().sum(F<OpenMesh::VertexHandle>()), mesh_.valence(fh));
|
||||
for (auto fh : mesh_.faces())
|
||||
EXPECT_EQ(fh.halfedges().sum(F<OpenMesh::HalfedgeHandle>()), mesh_.valence(fh));
|
||||
for (auto fh : mesh_.faces())
|
||||
EXPECT_EQ(fh.edges().sum(F<OpenMesh::EdgeHandle>()), mesh_.valence(fh));
|
||||
for (auto fh : mesh_.faces())
|
||||
EXPECT_EQ(fh.faces().sum(F<OpenMesh::FaceHandle>()), 3u);
|
||||
}
|
||||
|
||||
|
||||
/* Test if Property Manager can be used in smart ranges
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, PropertyManagerAsFunctor)
|
||||
{
|
||||
OpenMesh::VProp<Mesh::Point> myPos(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
myPos(vh) = mesh_.point(vh);
|
||||
|
||||
Mesh::Point cog(0,0,0);
|
||||
for (auto vh : mesh_.vertices())
|
||||
cog += mesh_.point(vh);
|
||||
cog /= mesh_.n_vertices();
|
||||
|
||||
auto cog2 = mesh_.vertices().avg(myPos);
|
||||
|
||||
EXPECT_LT(norm(cog - cog2), 0.00001) << "Computed center of gravities are significantly different.";
|
||||
}
|
||||
|
||||
/* Test to vector
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, ToVector)
|
||||
{
|
||||
OpenMesh::HProp<OpenMesh::Vec2d> uvs(mesh_);
|
||||
|
||||
for (auto heh : mesh_.halfedges())
|
||||
uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7);
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
auto tri_uvs = fh.halfedges().to_vector(uvs);
|
||||
auto heh_handles = fh.halfedges().to_vector();
|
||||
for (auto heh : heh_handles)
|
||||
heh.next();
|
||||
}
|
||||
|
||||
auto vertex_vec = mesh_.vertices().to_vector();
|
||||
for (auto vh : vertex_vec)
|
||||
vh.out();
|
||||
}
|
||||
|
||||
/* Test to array
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, ToArray)
|
||||
{
|
||||
OpenMesh::HProp<OpenMesh::Vec2d> uvs(mesh_);
|
||||
|
||||
for (auto heh : mesh_.halfedges())
|
||||
uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7);
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
fh.halfedges().to_array<3>(uvs);
|
||||
fh.halfedges().to_array<3>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Test bounding box
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, BoundingBox)
|
||||
{
|
||||
// The custom vecs OpenMesh are tested with here do not implement a min or max function.
|
||||
// Thus we convert here.
|
||||
OpenMesh::VProp<OpenMesh::Vec3f> myPos(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
myPos(vh)[i] = mesh_.point(vh)[i];
|
||||
|
||||
auto bb_min = mesh_.vertices().min(myPos);
|
||||
auto bb_max = mesh_.vertices().max(myPos);
|
||||
mesh_.vertices().minmax(myPos);
|
||||
|
||||
EXPECT_LT(norm(bb_min - OpenMesh::Vec3f(-1,-1,-1)), 0.000001) << "Bounding box minimum seems off";
|
||||
EXPECT_LT(norm(bb_max - OpenMesh::Vec3f( 1, 1, 1)), 0.000001) << "Bounding box maximum seems off";
|
||||
|
||||
|
||||
auto uvs = OpenMesh::makeTemporaryProperty<OpenMesh::HalfedgeHandle, OpenMesh::Vec2d>(mesh_);
|
||||
for (auto heh : mesh_.halfedges())
|
||||
uvs(heh) = OpenMesh::Vec2d(heh.idx(), (heh.idx() * 13)%7);
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
fh.halfedges().min(uvs);
|
||||
fh.halfedges().max(uvs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Test for each
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, ForEach)
|
||||
{
|
||||
std::vector<int> vec;
|
||||
auto f = [&vec](OpenMesh::VertexHandle vh) { vec.push_back(vh.idx()); };
|
||||
|
||||
mesh_.vertices().for_each(f);
|
||||
|
||||
ASSERT_EQ(vec.size(), mesh_.n_vertices()) << "vec has wrong size";
|
||||
for (size_t i = 0; i < vec.size(); ++i)
|
||||
EXPECT_EQ(vec[i], i) << "wrong index in vector";
|
||||
}
|
||||
|
||||
|
||||
/* Test filter
|
||||
*/
|
||||
TEST_F(OpenMeshSmartRanges, Filtered)
|
||||
{
|
||||
using VH = OpenMesh::VertexHandle;
|
||||
using FH = OpenMesh::FaceHandle;
|
||||
|
||||
auto is_even = [](VH vh) { return vh.idx() % 2 == 0; };
|
||||
auto is_odd = [](VH vh) { return vh.idx() % 2 == 1; };
|
||||
auto is_divisible_by_3 = [](VH vh) { return vh.idx() % 3 == 0; };
|
||||
auto to_id = [](VH vh) { return vh.idx(); };
|
||||
|
||||
auto even_vertices = mesh_.vertices().filtered(is_even).to_vector(to_id);
|
||||
EXPECT_EQ(even_vertices.size(), 4);
|
||||
EXPECT_EQ(even_vertices[0], 0);
|
||||
EXPECT_EQ(even_vertices[1], 2);
|
||||
EXPECT_EQ(even_vertices[2], 4);
|
||||
EXPECT_EQ(even_vertices[3], 6);
|
||||
|
||||
auto odd_vertices = mesh_.vertices().filtered(is_odd).to_vector(to_id);
|
||||
EXPECT_EQ(odd_vertices.size(), 4);
|
||||
EXPECT_EQ(odd_vertices[0], 1);
|
||||
EXPECT_EQ(odd_vertices[1], 3);
|
||||
EXPECT_EQ(odd_vertices[2], 5);
|
||||
EXPECT_EQ(odd_vertices[3], 7);
|
||||
|
||||
auto even_3_vertices = mesh_.vertices().filtered(is_even).filtered(is_divisible_by_3).to_vector(to_id);
|
||||
EXPECT_EQ(even_3_vertices.size(), 2);
|
||||
EXPECT_EQ(even_3_vertices[0], 0);
|
||||
EXPECT_EQ(even_3_vertices[1], 6);
|
||||
|
||||
auto odd_3_vertices = mesh_.vertices().filtered(is_odd).filtered(is_divisible_by_3).to_vector(to_id);
|
||||
EXPECT_EQ(odd_3_vertices.size(), 1);
|
||||
EXPECT_EQ(odd_3_vertices[0], 3);
|
||||
|
||||
|
||||
// create a vector of vertices in the order they are visited when iterating over face vertices, but every vertex only once
|
||||
std::vector<VH> vertices;
|
||||
OpenMesh::VProp<bool> to_be_processed(true, mesh_);
|
||||
auto store_vertex = [&](VH vh) { to_be_processed(vh) = false; vertices.push_back(vh); };
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
fh.vertices().filtered(to_be_processed).for_each(store_vertex);
|
||||
|
||||
EXPECT_EQ(vertices.size(), mesh_.n_vertices()) << " number of visited vertices not correct";
|
||||
EXPECT_TRUE(mesh_.vertices().all_of([&](VH vh) { return !to_be_processed(vh); })) << "did not visit all vertices";
|
||||
|
||||
{
|
||||
OpenMesh::FProp<bool> to_be_visited(true, mesh_);
|
||||
int visited_faces_in_main_loop = 0;
|
||||
int visited_faces_in_sub_loop = 0;
|
||||
for (auto fh : mesh_.faces().filtered(to_be_visited))
|
||||
{
|
||||
to_be_visited(fh) = false;
|
||||
++visited_faces_in_main_loop;
|
||||
for (auto neighbor : fh.faces().filtered(to_be_visited))
|
||||
{
|
||||
to_be_visited(neighbor) = false;
|
||||
++visited_faces_in_sub_loop;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_LT(visited_faces_in_main_loop, mesh_.n_faces()) << "Visted more faces than expected";
|
||||
EXPECT_TRUE(mesh_.faces().all_of([&](FH fh) { return !to_be_visited(fh); })) << "did not visit all faces";
|
||||
EXPECT_EQ(visited_faces_in_main_loop + visited_faces_in_sub_loop, mesh_.n_faces()) << "Did not visited all faces exactly once";
|
||||
}
|
||||
|
||||
{
|
||||
OpenMesh::FProp<bool> to_be_visited(true, mesh_);
|
||||
const auto& to_be_visited_const_ref = to_be_visited;
|
||||
int visited_faces_in_main_loop = 0;
|
||||
int visited_faces_in_sub_loop = 0;
|
||||
for (auto fh : mesh_.faces().filtered(to_be_visited_const_ref))
|
||||
{
|
||||
to_be_visited(fh) = false;
|
||||
++visited_faces_in_main_loop;
|
||||
for (auto neighbor : fh.faces().filtered(to_be_visited_const_ref))
|
||||
{
|
||||
to_be_visited(neighbor) = false;
|
||||
++visited_faces_in_sub_loop;
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_LT(visited_faces_in_main_loop, mesh_.n_faces()) << "Visted more faces than expected";
|
||||
EXPECT_TRUE(mesh_.faces().all_of([&](FH fh) { return !to_be_visited(fh); })) << "did not visit all faces";
|
||||
EXPECT_EQ(visited_faces_in_main_loop + visited_faces_in_sub_loop, mesh_.n_faces()) << "Did not visited all faces exactly once";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
252
src/Unittests/unittests_smarttagger.cc
Normal file
252
src/Unittests/unittests_smarttagger.cc
Normal file
@@ -0,0 +1,252 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <iostream>
|
||||
#include <OpenMesh/Tools/SmartTagger/SmartTaggerT.hh>
|
||||
|
||||
namespace {
|
||||
|
||||
class OpenMeshSmartTagger : public OpenMeshBase {
|
||||
|
||||
protected:
|
||||
|
||||
// This function is called before each test is run
|
||||
virtual void SetUp() {
|
||||
|
||||
// Do some initial stuff with the member data here...
|
||||
}
|
||||
|
||||
// This function is called after all tests are through
|
||||
virtual void TearDown() {
|
||||
|
||||
// Do some final stuff with the member data here...
|
||||
}
|
||||
|
||||
// Member already defined in OpenMeshBase
|
||||
//Mesh mesh_;
|
||||
};
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* Checks SmartTagger on vertices
|
||||
*/
|
||||
TEST_F(OpenMeshSmartTagger, SmartTaggerVertices) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[7];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(3, 0, 0));
|
||||
|
||||
|
||||
// Add two faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
/* Test setup:
|
||||
0 ==== 2
|
||||
|\ /|\
|
||||
| \ / | \
|
||||
| 1 | 5
|
||||
| / \ | /
|
||||
|/ \|/
|
||||
3 ==== 4
|
||||
|
||||
*/
|
||||
|
||||
|
||||
OpenMesh::SmartTaggerVT< Mesh > tagger(mesh_);
|
||||
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after init!";
|
||||
|
||||
// Reset tagged flag on all vertices
|
||||
tagger.untag_all();
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after first untag_all!";
|
||||
|
||||
|
||||
// Set tagged:
|
||||
tagger.set_tag(vhandle[2]);
|
||||
tagger.set_tag(vhandle[4]);
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged!";
|
||||
EXPECT_TRUE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be tagged!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged!";
|
||||
EXPECT_TRUE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be tagged!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged!";
|
||||
|
||||
// Reset tagged flag on all vertices
|
||||
tagger.untag_all();
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[0] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[1] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[2] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[3] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[4] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged(vhandle[5] ) ) << "Vertex should be untagged after second untag_all!";
|
||||
|
||||
}
|
||||
|
||||
/* Checks SmartTagger on vertices
|
||||
*/
|
||||
TEST_F(OpenMeshSmartTagger, SmartTaggerFaces) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[7];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(0,-1, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(3, 0, 0));
|
||||
|
||||
|
||||
// Add two faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
Mesh::FaceHandle fh1 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
Mesh::FaceHandle fh2 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
Mesh::FaceHandle fh3 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
Mesh::FaceHandle fh4 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
Mesh::FaceHandle fh5 = mesh_.add_face(face_vhandles);
|
||||
|
||||
/* Test setup:
|
||||
0 ==== 2
|
||||
|\ /|\
|
||||
| \ / | \
|
||||
| 1 | 5
|
||||
| / \ | /
|
||||
|/ \|/
|
||||
3 ==== 4
|
||||
|
||||
*/
|
||||
|
||||
|
||||
OpenMesh::SmartTaggerFT< Mesh > tagger(mesh_);
|
||||
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after init!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after init!";
|
||||
|
||||
|
||||
// Reset tagged flag on all vertices
|
||||
tagger.untag_all();
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after first untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after first untag_all!";
|
||||
|
||||
|
||||
|
||||
// Set tagged:
|
||||
tagger.set_tag(fh3);
|
||||
tagger.set_tag(fh5);
|
||||
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged(fh1 ) ) << "Face should be untagged!";
|
||||
EXPECT_FALSE( tagger.is_tagged(fh2 ) ) << "Face should be untagged!";
|
||||
EXPECT_TRUE( tagger.is_tagged(fh3 ) ) << "Face should be tagged!";
|
||||
EXPECT_FALSE( tagger.is_tagged(fh4 ) ) << "Face should be tagged!";
|
||||
EXPECT_TRUE( tagger.is_tagged(fh5 ) ) << "Face should be tagged!";
|
||||
|
||||
|
||||
// Reset tagged flag on all vertices
|
||||
tagger.untag_all();
|
||||
|
||||
EXPECT_FALSE( tagger.is_tagged( fh1 ) ) << "Face should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh2 ) ) << "Face should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh3 ) ) << "Face should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh4 ) ) << "Face should be untagged after second untag_all!";
|
||||
EXPECT_FALSE( tagger.is_tagged( fh5 ) ) << "Face should be untagged after second untag_all!";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -91,13 +91,15 @@ TEST_F(OpenMeshSplitEdgeCopyTriangleMesh, SplitEdgeCopyTriangleMesh) {
|
||||
//set internal property
|
||||
mesh_.status(eh).set_tagged(true);
|
||||
|
||||
// split face with new vertex
|
||||
mesh_.split_edge_copy(eh, vhandle[3]);
|
||||
// split edge with new vertex
|
||||
mesh_.split_copy(eh, vhandle[3]);
|
||||
|
||||
// Check setup
|
||||
Mesh::EdgeHandle eh0 = mesh_.edge_handle( mesh_.next_halfedge_handle( mesh_.halfedge_handle(eh, 1) ) );
|
||||
EXPECT_EQ(999, mesh_.property(eprop_int, eh0)) << "Different Property value";
|
||||
EXPECT_TRUE(mesh_.status(eh0).tagged()) << "Different internal property value";
|
||||
|
||||
EXPECT_EQ(3u, mesh_.valence(fh)) << "Face of TriMesh has valence other than 3";
|
||||
}
|
||||
|
||||
/* splits an edge that has a property in a poly mesh with split_edge_copy
|
||||
@@ -125,7 +127,7 @@ TEST_F(OpenMeshSplitEdgeCopyPolyMesh, SplitEdgeCopyPolymesh) {
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
PolyMesh::FaceHandle fh = mesh_.add_face(face_vhandles);
|
||||
mesh_.add_face(face_vhandles);
|
||||
PolyMesh::EdgeHandle eh = *mesh_.edges_begin();
|
||||
|
||||
// Test setup:
|
||||
@@ -152,4 +154,102 @@ TEST_F(OpenMeshSplitEdgeCopyPolyMesh, SplitEdgeCopyPolymesh) {
|
||||
EXPECT_EQ(999, mesh_.property(eprop_int, eh0)) << "Different Property value";
|
||||
EXPECT_TRUE(mesh_.status(eh0).tagged()) << "Different internal property value";
|
||||
}
|
||||
|
||||
|
||||
/* splits an edge in a triangle mesh that has a face property with split_edge_copy
|
||||
* the property should be copied to the new edge
|
||||
*/
|
||||
TEST_F(OpenMeshSplitEdgeCopyTriangleMesh, SplitEdgeCopyFacePropertiesTriangleMesh) {
|
||||
|
||||
mesh_.clear();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
static_assert(std::is_same<decltype (mesh_), Mesh>::value, "Mesh is not a triangle mesh");
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[4];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
|
||||
Mesh::VertexHandle inner_vertex = mesh_.add_vertex(Mesh::Point(0.5, 0.5, 0));
|
||||
Mesh::VertexHandle boundary_vertex = mesh_.add_vertex(Mesh::Point(0.0, 0.5, 0));
|
||||
|
||||
// Add two faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
|
||||
Mesh::FaceHandle fh0 = mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
Mesh::FaceHandle fh1 = mesh_.add_face(face_vhandles);
|
||||
|
||||
Mesh::EdgeHandle inner_edge = Mesh::EdgeHandle(2);
|
||||
|
||||
EXPECT_EQ(mesh_.n_faces(), 2u);
|
||||
|
||||
// Test setup:
|
||||
// 1 --- 2
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// 0 --- 3
|
||||
|
||||
// set property
|
||||
OpenMesh::FPropHandleT<int> fprop_int;
|
||||
mesh_.add_property(fprop_int);
|
||||
mesh_.property(fprop_int, fh0) = 13;
|
||||
mesh_.property(fprop_int, fh1) = 17;
|
||||
//set internal property
|
||||
mesh_.status(fh0).set_tagged(true);
|
||||
|
||||
// 2 to 4 split
|
||||
mesh_.split_copy(inner_edge, inner_vertex);
|
||||
|
||||
EXPECT_EQ(mesh_.n_faces(), 4u);
|
||||
|
||||
for (auto fh : mesh_.faces())
|
||||
{
|
||||
EXPECT_EQ(3u, mesh_.valence(fh));
|
||||
}
|
||||
|
||||
// Check setup
|
||||
Mesh::HalfedgeHandle heh21 = mesh_.find_halfedge(vhandle[2], vhandle[1]);
|
||||
Mesh::HalfedgeHandle heh10 = mesh_.find_halfedge(vhandle[1], vhandle[0]);
|
||||
Mesh::HalfedgeHandle heh03 = mesh_.find_halfedge(vhandle[0], vhandle[3]);
|
||||
Mesh::HalfedgeHandle heh32 = mesh_.find_halfedge(vhandle[3], vhandle[2]);
|
||||
|
||||
EXPECT_EQ(13, mesh_.property(fprop_int, mesh_.face_handle(heh21))) << "Different Property value";
|
||||
EXPECT_EQ(13, mesh_.property(fprop_int, mesh_.face_handle(heh10))) << "Different Property value";
|
||||
EXPECT_EQ(17, mesh_.property(fprop_int, mesh_.face_handle(heh03))) << "Different Property value";
|
||||
EXPECT_EQ(17, mesh_.property(fprop_int, mesh_.face_handle(heh32))) << "Different Property value";
|
||||
EXPECT_TRUE(mesh_.status(mesh_.face_handle(heh21)).tagged()) << "Different internal property value";
|
||||
EXPECT_TRUE(mesh_.status(mesh_.face_handle(heh10)).tagged()) << "Different internal property value";
|
||||
EXPECT_FALSE(mesh_.status(mesh_.face_handle(heh03)).tagged()) << "Different internal property value";
|
||||
EXPECT_FALSE(mesh_.status(mesh_.face_handle(heh32)).tagged()) << "Different internal property value";
|
||||
|
||||
// also test boundary split
|
||||
Mesh::EdgeHandle boundary_edge = mesh_.edge_handle(heh10);
|
||||
|
||||
// 1 to 2 split
|
||||
mesh_.split_copy(boundary_edge, boundary_vertex);
|
||||
|
||||
Mesh::HalfedgeHandle heh1b = mesh_.find_halfedge(vhandle[1], boundary_vertex);
|
||||
Mesh::HalfedgeHandle hehb0 = mesh_.find_halfedge(boundary_vertex, vhandle[0]);
|
||||
|
||||
EXPECT_EQ(13, mesh_.property(fprop_int, mesh_.face_handle(heh1b))) << "Different Property value";
|
||||
EXPECT_EQ(13, mesh_.property(fprop_int, mesh_.face_handle(hehb0))) << "Different Property value";
|
||||
EXPECT_TRUE(mesh_.status(mesh_.face_handle(heh1b)).tagged()) << "Different internal property value";
|
||||
EXPECT_TRUE(mesh_.status(mesh_.face_handle(hehb0)).tagged()) << "Different internal property value";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh>
|
||||
#include <OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh>
|
||||
|
||||
@@ -147,6 +149,371 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Sqrt3) {
|
||||
EXPECT_EQ(216u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with sqrt3";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Sqrt3_delete_vertex) {
|
||||
|
||||
for (bool collect_garbage : { false, true })
|
||||
{
|
||||
mesh_.clear();
|
||||
|
||||
// Request status flags to use delete and garbage collection
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add eight faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// 3 === 4 === 5
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// 0 === 1 === 2
|
||||
|
||||
// Delete one vertex
|
||||
mesh_.delete_vertex(vhandle[1]);
|
||||
// Check setup
|
||||
if (collect_garbage)
|
||||
{
|
||||
mesh_.garbage_collection();
|
||||
EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::Sqrt3T<Mesh> sqrt3;
|
||||
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
sqrt3.attach(mesh_);
|
||||
sqrt3( 3 );
|
||||
sqrt3.detach();
|
||||
|
||||
if (!collect_garbage)
|
||||
mesh_.garbage_collection(); // if we did not collect garbage before, do so now
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(94u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with sqrt3";
|
||||
EXPECT_EQ(162u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with sqrt3";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop) {
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add eight faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// 3 === 4 === 5
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// 0 === 1 === 2
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::LoopT<Mesh> loop;
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
loop.attach(mesh_);
|
||||
loop( 3 );
|
||||
loop.detach();
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(289u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with loop";
|
||||
EXPECT_EQ(512u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with loop";
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop_delete_vertex) {
|
||||
|
||||
for (bool collect_garbage : { false, true })
|
||||
{
|
||||
mesh_.clear();
|
||||
|
||||
// Request status flags to use delete and garbage collection
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add eight faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// 3 === 4 === 5
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// 0 === 1 === 2
|
||||
|
||||
// Delete one vertex
|
||||
mesh_.delete_vertex(vhandle[1]);
|
||||
if (collect_garbage)
|
||||
{
|
||||
mesh_.garbage_collection();
|
||||
// Check setup
|
||||
EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check setup
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::LoopT<Mesh> loop;
|
||||
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
loop.attach(mesh_);
|
||||
loop( 3 );
|
||||
loop.detach();
|
||||
|
||||
if (!collect_garbage)
|
||||
mesh_.garbage_collection(); // if we did not collect garbage before, do so now
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(225u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with loop";
|
||||
EXPECT_EQ(384u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with loop";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Define tests below
|
||||
@@ -232,6 +599,108 @@ TEST_F(OpenMeshSubdividerUniform_Poly, Subdivider_CatmullClark) {
|
||||
EXPECT_EQ(256u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Poly, Subdivider_CatmullClark_delete_vertex) {
|
||||
|
||||
for (bool collect_garbage : { false, true })
|
||||
{
|
||||
mesh_.clear();
|
||||
|
||||
// Request status flags to use delete and garbage collection
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add four faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// 3 === 4 === 5
|
||||
// | | |
|
||||
// | | |
|
||||
// | | |
|
||||
// 0 === 1 === 2
|
||||
|
||||
|
||||
mesh_.delete_vertex(vhandle[1]);
|
||||
// Check setup
|
||||
if (collect_garbage)
|
||||
{
|
||||
mesh_.garbage_collection();
|
||||
EXPECT_EQ(6u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(2u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(4u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::CatmullClarkT<PolyMesh> catmull;
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
catmull.attach(mesh_);
|
||||
catmull( 3 );
|
||||
catmull.detach();
|
||||
|
||||
if (!collect_garbage)
|
||||
mesh_.garbage_collection(); // if we did not collect garbage before, do so now
|
||||
|
||||
EXPECT_EQ(153u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with catmull clark";
|
||||
EXPECT_EQ(128u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark";
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a cube to a polymesh
|
||||
*/
|
||||
TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) {
|
||||
@@ -329,4 +798,364 @@ TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) {
|
||||
EXPECT_EQ(26u, mesh_.n_faces()) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint_delete_vertex) {
|
||||
|
||||
for (bool collect_garbage : { false, true })
|
||||
{
|
||||
mesh_.clear();
|
||||
|
||||
// Request status flags to use delete and garbage collection
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[8];
|
||||
vhandle[0] = mesh_.add_vertex(PolyMesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh_.add_vertex(PolyMesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh_.add_vertex(PolyMesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh_.add_vertex(PolyMesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh_.add_vertex(PolyMesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh_.add_vertex(PolyMesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh_.add_vertex(PolyMesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh_.add_vertex(PolyMesh::Point(-1, 1, -1));
|
||||
|
||||
// Add six faces to form a cube
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
|
||||
// Test setup:
|
||||
//
|
||||
//
|
||||
// 3 ======== 2
|
||||
// / /|
|
||||
// / / | z
|
||||
// 0 ======== 1 | |
|
||||
// | | | | y
|
||||
// | 7 | 6 | /
|
||||
// | | / | /
|
||||
// | |/ |/
|
||||
// 4 ======== 5 -------> x
|
||||
//
|
||||
|
||||
mesh_.delete_vertex(vhandle[1]);
|
||||
// Check setup
|
||||
if (collect_garbage)
|
||||
{
|
||||
mesh_.garbage_collection();
|
||||
EXPECT_EQ(9u, mesh_.n_edges()) << "Wrong number of Edges";
|
||||
EXPECT_EQ(18u, mesh_.n_halfedges()) << "Wrong number of HalfEdges";
|
||||
EXPECT_EQ(7u, mesh_.n_vertices()) << "Wrong number of vertices";
|
||||
EXPECT_EQ(3u, mesh_.n_faces()) << "Wrong number of faces";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(12u, mesh_.n_edges()) << "Wrong number of Edges";
|
||||
EXPECT_EQ(24u, mesh_.n_halfedges()) << "Wrong number of HalfEdges";
|
||||
EXPECT_EQ(8u, mesh_.n_vertices()) << "Wrong number of vertices";
|
||||
EXPECT_EQ(6u, mesh_.n_faces()) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// Check setup
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::MidpointT<PolyMesh> midpoint;
|
||||
|
||||
// Execute 2 subdivision steps
|
||||
midpoint.attach(mesh_);
|
||||
midpoint(2);
|
||||
midpoint.detach();
|
||||
|
||||
if (!collect_garbage)
|
||||
mesh_.garbage_collection(); // if we did not collect garbage before, do so now
|
||||
|
||||
// Check Result
|
||||
EXPECT_EQ(15u, mesh_.n_edges()) << "Wrong number of Edges";
|
||||
EXPECT_EQ(30u, mesh_.n_halfedges()) << "Wrong number of HalfEdges";
|
||||
EXPECT_EQ(12u, mesh_.n_vertices()) << "Wrong number of vertices";
|
||||
EXPECT_EQ(4u, mesh_.n_faces()) << "Wrong number of faces";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly) {
|
||||
mesh_.clear();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add eight faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// 3 === 4 === 5
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// 0 === 1 === 2
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::ModifiedButterflyT<Mesh> butter;
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
butter.attach(mesh_);
|
||||
butter( 3 );
|
||||
butter.detach();
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(289u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with loop";
|
||||
EXPECT_EQ(512u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with loop";
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly_delete_vertex) {
|
||||
|
||||
for (bool collect_garbage : { false, true })
|
||||
{
|
||||
mesh_.clear();
|
||||
|
||||
// Request status flags to use delete and garbage collection
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[9];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0));
|
||||
vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
|
||||
vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
|
||||
vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
|
||||
|
||||
// Add eight faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
face_vhandles.push_back(vhandle[6]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
face_vhandles.push_back(vhandle[7]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
face_vhandles.clear();
|
||||
|
||||
face_vhandles.push_back(vhandle[4]);
|
||||
face_vhandles.push_back(vhandle[5]);
|
||||
face_vhandles.push_back(vhandle[8]);
|
||||
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
// Test setup:
|
||||
// 6 === 7 === 8
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// | / | / |
|
||||
// 3 === 4 === 5
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// | / | \ |
|
||||
// 0 === 1 === 2
|
||||
|
||||
|
||||
// Delete one vertex
|
||||
mesh_.delete_vertex(vhandle[1]);
|
||||
// Check setup
|
||||
if (collect_garbage)
|
||||
{
|
||||
mesh_.garbage_collection();
|
||||
EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices";
|
||||
EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces";
|
||||
}
|
||||
|
||||
// Initialize subdivider
|
||||
OpenMesh::Subdivider::Uniform::ModifiedButterflyT<Mesh> butter;
|
||||
|
||||
|
||||
// Execute 3 subdivision steps
|
||||
butter.attach(mesh_);
|
||||
butter( 3 );
|
||||
butter.detach();
|
||||
|
||||
if (!collect_garbage)
|
||||
mesh_.garbage_collection(); // if we did not collect garbage before, do so now
|
||||
|
||||
// Check setup
|
||||
EXPECT_EQ(225u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with butter";
|
||||
EXPECT_EQ(384u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with butter";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -741,5 +741,4 @@ TEST_F(OpenMeshCollapse, DeletedStatus) {
|
||||
EXPECT_FALSE(mesh_.status(mesh_.opposite_halfedge_handle(bottom_right)).deleted()) << "Halfedge from vertex 5 to vertex 3 is deleted";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -773,7 +773,7 @@ TEST_F(OpenMeshIterators, FaceIterEmptyMeshOneDeletedFace) {
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
|
||||
// Add two faces
|
||||
// Add one faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
@@ -841,4 +841,162 @@ TEST_F(OpenMeshIterators, FaceIterEmptyMeshOneDeletedFace) {
|
||||
mesh_.release_face_status();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Test range iterators
|
||||
*/
|
||||
TEST_F(OpenMeshIterators, RangeIterators) {
|
||||
|
||||
mesh_.clear();
|
||||
|
||||
// request delete_face capability
|
||||
mesh_.request_vertex_status();
|
||||
mesh_.request_edge_status();
|
||||
mesh_.request_halfedge_status();
|
||||
mesh_.request_face_status();
|
||||
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[4];
|
||||
|
||||
vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
|
||||
|
||||
// Add two faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
mesh_.add_face(face_vhandles);
|
||||
|
||||
face_vhandles.clear();
|
||||
face_vhandles.push_back(vhandle[0]);
|
||||
face_vhandles.push_back(vhandle[3]);
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
Mesh::FaceHandle fh = mesh_.add_face(face_vhandles);
|
||||
|
||||
// Delete one face
|
||||
mesh_.delete_face(fh);
|
||||
|
||||
// Test setup (right face deleted)
|
||||
// 1 --- 2
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// 0 --- 3
|
||||
|
||||
|
||||
// ====== Faces ======
|
||||
|
||||
int count_faces_iter = 0;
|
||||
for (auto f_it = mesh_.faces_begin(); f_it != mesh_.faces_end(); ++f_it)
|
||||
++count_faces_iter;
|
||||
EXPECT_EQ(2, count_faces_iter) << "Wrong number of visited faces.";
|
||||
|
||||
int count_faces_skipping_iter = 0;
|
||||
for (auto f_it = mesh_.faces_sbegin(); f_it != mesh_.faces_end(); ++f_it)
|
||||
++count_faces_skipping_iter;
|
||||
EXPECT_EQ(1, count_faces_skipping_iter) << "Wrong number of visited faces.";
|
||||
|
||||
int count_faces_range = 0;
|
||||
for (auto fh : mesh_.faces())
|
||||
if (fh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_faces_range;
|
||||
EXPECT_EQ(1, count_faces_range) << "Wrong number of visited faces.";
|
||||
|
||||
int count_faces_range_all = 0;
|
||||
for (auto fh : mesh_.all_faces())
|
||||
if (fh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_faces_range_all;
|
||||
EXPECT_EQ(2, count_faces_range_all) << "Wrong number of visited faces.";
|
||||
|
||||
|
||||
// ====== Edges ======
|
||||
|
||||
int count_edges_iter = 0;
|
||||
for (auto e_it = mesh_.edges_begin(); e_it != mesh_.edges_end(); ++e_it)
|
||||
++count_edges_iter;
|
||||
EXPECT_EQ(5, count_edges_iter) << "Wrong number of visited edges.";
|
||||
|
||||
int count_edges_skipping_iter = 0;
|
||||
for (auto e_it = mesh_.edges_sbegin(); e_it != mesh_.edges_end(); ++e_it)
|
||||
++count_edges_skipping_iter;
|
||||
EXPECT_EQ(3, count_edges_skipping_iter) << "Wrong number of visited edges.";
|
||||
|
||||
int count_edges_range = 0;
|
||||
for (auto eh : mesh_.edges())
|
||||
if (eh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_edges_range;
|
||||
EXPECT_EQ(3, count_edges_range) << "Wrong number of visited edges.";
|
||||
|
||||
int count_edges_range_all = 0;
|
||||
for (auto eh : mesh_.all_edges())
|
||||
if (eh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_edges_range_all;
|
||||
EXPECT_EQ(5, count_edges_range_all) << "Wrong number of visited edges.";
|
||||
|
||||
|
||||
// ====== Halfedges ======
|
||||
|
||||
int count_halfedges_iter = 0;
|
||||
for (auto h_it = mesh_.halfedges_begin(); h_it != mesh_.halfedges_end(); ++h_it)
|
||||
++count_halfedges_iter;
|
||||
EXPECT_EQ(10, count_halfedges_iter) << "Wrong number of visited halfedges.";
|
||||
|
||||
int count_halfedges_skipping_iter = 0;
|
||||
for (auto h_it = mesh_.halfedges_sbegin(); h_it != mesh_.halfedges_end(); ++h_it)
|
||||
++count_halfedges_skipping_iter;
|
||||
EXPECT_EQ(6, count_halfedges_skipping_iter) << "Wrong number of visited halfedges.";
|
||||
|
||||
int count_halfedges_range = 0;
|
||||
for (auto heh : mesh_.halfedges())
|
||||
if (heh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_halfedges_range;
|
||||
EXPECT_EQ(6, count_halfedges_range) << "Wrong number of visited halfedges.";
|
||||
|
||||
int count_halfedges_range_all = 0;
|
||||
for (auto heh : mesh_.all_halfedges())
|
||||
if (heh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_halfedges_range_all;
|
||||
EXPECT_EQ(10, count_halfedges_range_all) << "Wrong number of visited halfedges.";
|
||||
|
||||
|
||||
// ====== Vertices ======
|
||||
|
||||
int count_vertices_iter = 0;
|
||||
for (auto v_it = mesh_.vertices_begin(); v_it != mesh_.vertices_end(); ++v_it)
|
||||
++count_vertices_iter;
|
||||
EXPECT_EQ(4, count_vertices_iter) << "Wrong number of visited vertices.";
|
||||
|
||||
int count_vertices_skipping_iter = 0;
|
||||
for (auto v_it = mesh_.vertices_sbegin(); v_it != mesh_.vertices_end(); ++v_it)
|
||||
++count_vertices_skipping_iter;
|
||||
EXPECT_EQ(3, count_vertices_skipping_iter) << "Wrong number of visited vertices.";
|
||||
|
||||
int count_vertices_range = 0;
|
||||
for (auto vh : mesh_.vertices())
|
||||
if (vh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_vertices_range;
|
||||
EXPECT_EQ(3, count_vertices_range) << "Wrong number of visited vertices.";
|
||||
|
||||
int count_vertices_range_all = 0;
|
||||
for (auto vh : mesh_.all_vertices())
|
||||
if (vh.is_valid()) // not actually necessary but fixes unused variable warning
|
||||
++count_vertices_range_all;
|
||||
EXPECT_EQ(4, count_vertices_range_all) << "Wrong number of visited vertices.";
|
||||
|
||||
|
||||
mesh_.release_vertex_status();
|
||||
mesh_.release_edge_status();
|
||||
mesh_.release_halfedge_status();
|
||||
mesh_.release_face_status();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -164,7 +164,8 @@ TEST_F(OpenMeshOthers, CalcDihedralAngre ) {
|
||||
EXPECT_EQ( 0.0 , mesh_.calc_dihedral_angle(eh) ) << "Wrong Dihedral angle!" << std::endl;
|
||||
|
||||
// Modify point
|
||||
Mesh::Point tmp = ( Mesh::Point(0.0, 0.0, -1.0) + Mesh::Point(1.0, 1.0, -1.0) ) * static_cast<Mesh::Point::value_type>(0.5);
|
||||
Mesh::Point tmp = ( Mesh::Point(0.0, 0.0, -1.0) + Mesh::Point(1.0, 1.0, -1.0) )
|
||||
* static_cast<OpenMesh::vector_traits<Mesh::Point>::value_type>(0.5);
|
||||
mesh_.point(vhandle[2]) = tmp;
|
||||
|
||||
double difference = fabs( 1.36944 - mesh_.calc_dihedral_angle(eh) );
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
#include <Unittests/unittests_common.hh>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@@ -197,7 +198,7 @@ public:
|
||||
|
||||
public:
|
||||
// construct with a given mesh
|
||||
SmootherT(Mesh& _mesh)
|
||||
explicit SmootherT(Mesh& _mesh)
|
||||
: mesh_(_mesh)
|
||||
{
|
||||
mesh_.add_property( cog_ );
|
||||
@@ -445,39 +446,34 @@ TEST_F(OpenMeshTutorials, using_iterators_and_circulators) {
|
||||
TEST_F(OpenMeshTutorials, using_custom_properties) {
|
||||
MyMesh mesh;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "output.off");
|
||||
EXPECT_TRUE(ok) << "Cannot read mesh from file 'output.off'";
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "cube_noisy.off");
|
||||
EXPECT_TRUE(ok) << "Cannot read mesh from file 'cube_noisy.off'";
|
||||
|
||||
// this vertex property stores the computed centers of gravity
|
||||
OpenMesh::VPropHandleT<MyMesh::Point> cogs;
|
||||
mesh.add_property(cogs);
|
||||
const int iterations = 100;
|
||||
|
||||
// smoothing mesh N times
|
||||
MyMesh::VertexIter v_it, v_end(mesh.vertices_end());
|
||||
MyMesh::VertexVertexIter vv_it;
|
||||
MyMesh::Point cog;
|
||||
MyMesh::Scalar valence;
|
||||
unsigned int i, N(100);
|
||||
|
||||
for (i=0; i < N; ++i)
|
||||
{
|
||||
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
|
||||
{
|
||||
mesh.property(cogs,*v_it).vectorize(0.0f);
|
||||
valence = 0.0;
|
||||
// Add a vertex property storing the computed centers of gravity
|
||||
auto cog = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
for (vv_it = mesh.vv_iter( *v_it ); vv_it.is_valid(); ++vv_it)
|
||||
{
|
||||
mesh.property(cogs,*v_it) += mesh.point( *vv_it );
|
||||
++valence;
|
||||
// Smooth the mesh several times
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Iterate over all vertices to compute centers of gravity
|
||||
for (const auto& vh : mesh.vertices()) {
|
||||
cog[vh] = {0,0,0};
|
||||
int valence = 0;
|
||||
// Iterate over all 1-ring vertices around vh
|
||||
for (const auto& vvh : mesh.vv_range(vh)) {
|
||||
cog[vh] += mesh.point(vvh);
|
||||
++valence;
|
||||
}
|
||||
cog[vh] /= valence;
|
||||
}
|
||||
// Move all vertices to the previously computed positions
|
||||
for (const auto& vh : mesh.vertices()) {
|
||||
mesh.point(vh) = cog[vh];
|
||||
}
|
||||
mesh.property(cogs,*v_it) /= valence;
|
||||
}
|
||||
|
||||
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
|
||||
if ( !mesh.is_boundary( *v_it ) )
|
||||
mesh.set_point( *v_it, mesh.property(cogs,*v_it) );
|
||||
}
|
||||
} // The cog vertex property is removed from the mesh at the end of this scope
|
||||
|
||||
// write mesh
|
||||
ok = OpenMesh::IO::write_mesh(mesh, "smoothed_custom_properties_output.off");
|
||||
@@ -488,8 +484,8 @@ TEST_F(OpenMeshTutorials, using_custom_properties) {
|
||||
TEST_F(OpenMeshTutorials, using_STL_algorithms) {
|
||||
MyMeshWithTraits mesh;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "output.off");
|
||||
EXPECT_TRUE(ok) << "Cannot read mesh from file 'output.off'";
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "cube_noisy.off");
|
||||
EXPECT_TRUE(ok) << "Cannot read mesh from file 'cube_noisy.off'";
|
||||
|
||||
SmootherT<MyMeshWithTraits> smoother(mesh);
|
||||
smoother.smooth(100);
|
||||
@@ -619,20 +615,20 @@ TEST_F(OpenMeshTutorials, deleting_geometry_elements) {
|
||||
mesh.request_vertex_status();
|
||||
|
||||
// generate vertices
|
||||
MyMeshWithStatus::VertexHandle vhandle[8];
|
||||
MyMeshWithStatus::FaceHandle fhandle[6];
|
||||
Mesh::VertexHandle vhandle[8];
|
||||
Mesh::FaceHandle fhandle[6];
|
||||
|
||||
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));
|
||||
vhandle[0] = mesh.add_vertex(Mesh::Point(-1, -1, 1));
|
||||
vhandle[1] = mesh.add_vertex(Mesh::Point( 1, -1, 1));
|
||||
vhandle[2] = mesh.add_vertex(Mesh::Point( 1, 1, 1));
|
||||
vhandle[3] = mesh.add_vertex(Mesh::Point(-1, 1, 1));
|
||||
vhandle[4] = mesh.add_vertex(Mesh::Point(-1, -1, -1));
|
||||
vhandle[5] = mesh.add_vertex(Mesh::Point( 1, -1, -1));
|
||||
vhandle[6] = mesh.add_vertex(Mesh::Point( 1, 1, -1));
|
||||
vhandle[7] = mesh.add_vertex(Mesh::Point(-1, 1, -1));
|
||||
|
||||
// generate (quadrilateral) faces
|
||||
std::vector<MyMesh::VertexHandle> tmp_face_vhandles;
|
||||
std::vector<Mesh::VertexHandle> tmp_face_vhandles;
|
||||
tmp_face_vhandles.clear();
|
||||
tmp_face_vhandles.push_back(vhandle[0]);
|
||||
tmp_face_vhandles.push_back(vhandle[1]);
|
||||
@@ -807,10 +803,10 @@ TEST_F(OpenMeshTutorials, flipping_edges) {
|
||||
Mesh mesh;
|
||||
// Add some vertices
|
||||
Mesh::VertexHandle vhandle[4];
|
||||
vhandle[0] = mesh.add_vertex(MyMesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh.add_vertex(MyMesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh.add_vertex(MyMesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh.add_vertex(MyMesh::Point(1, 0, 0));
|
||||
vhandle[0] = mesh.add_vertex(Mesh::Point(0, 0, 0));
|
||||
vhandle[1] = mesh.add_vertex(Mesh::Point(0, 1, 0));
|
||||
vhandle[2] = mesh.add_vertex(Mesh::Point(1, 1, 0));
|
||||
vhandle[3] = mesh.add_vertex(Mesh::Point(1, 0, 0));
|
||||
// Add two faces
|
||||
std::vector<Mesh::VertexHandle> face_vhandles;
|
||||
face_vhandles.push_back(vhandle[2]);
|
||||
@@ -846,13 +842,13 @@ TEST_F(OpenMeshTutorials, collapsing_edges) {
|
||||
mesh.request_edge_status();
|
||||
// Add some vertices as in the illustration above
|
||||
PolyMesh::VertexHandle vhandle[7];
|
||||
vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, 1, 0));
|
||||
vhandle[1] = mesh.add_vertex(MyMesh::Point(-1, 3, 0));
|
||||
vhandle[2] = mesh.add_vertex(MyMesh::Point(0, 0, 0));
|
||||
vhandle[3] = mesh.add_vertex(MyMesh::Point(0, 2, 0));
|
||||
vhandle[4] = mesh.add_vertex(MyMesh::Point(0, 4, 0));
|
||||
vhandle[5] = mesh.add_vertex(MyMesh::Point(1, 1, 0));
|
||||
vhandle[6] = mesh.add_vertex(MyMesh::Point(1, 3, 0));
|
||||
vhandle[0] = mesh.add_vertex(PolyMesh::Point(-1, 1, 0));
|
||||
vhandle[1] = mesh.add_vertex(PolyMesh::Point(-1, 3, 0));
|
||||
vhandle[2] = mesh.add_vertex(PolyMesh::Point(0, 0, 0));
|
||||
vhandle[3] = mesh.add_vertex(PolyMesh::Point(0, 2, 0));
|
||||
vhandle[4] = mesh.add_vertex(PolyMesh::Point(0, 4, 0));
|
||||
vhandle[5] = mesh.add_vertex(PolyMesh::Point(1, 1, 0));
|
||||
vhandle[6] = mesh.add_vertex(PolyMesh::Point(1, 3, 0));
|
||||
// Add three quad faces
|
||||
std::vector<PolyMesh::VertexHandle> face_vhandles;
|
||||
face_vhandles.push_back(vhandle[1]);
|
||||
@@ -886,4 +882,44 @@ TEST_F(OpenMeshTutorials, collapsing_edges) {
|
||||
// Our mesh now looks like in the illustration above after the collapsing.
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshTutorials, using_smart_handles_and_smart_ranges) {
|
||||
MyMesh mesh;
|
||||
|
||||
bool ok = OpenMesh::IO::read_mesh(mesh, "cube_noisy.off");
|
||||
EXPECT_TRUE(ok) << "Cannot read mesh from file 'cube_noisy.off'";
|
||||
|
||||
const int iterations = 100;
|
||||
|
||||
{
|
||||
// Add a vertex property storing the laplace vector
|
||||
auto laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Add a vertex property storing the laplace of the laplace
|
||||
auto bi_laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Get a propertymanager of the points property of the mesh to use as functor
|
||||
auto points = OpenMesh::getPointsProperty(mesh);
|
||||
|
||||
// Smooth the mesh several times
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Iterate over all vertices to compute laplace vector
|
||||
for (const auto& vh : mesh.vertices())
|
||||
laplace(vh) = vh.vertices().avg(points) - points(vh);
|
||||
|
||||
// Iterate over all vertices to compute the laplace vector of the laplace vectors
|
||||
for (const auto& vh : mesh.vertices())
|
||||
bi_laplace(vh) = (vh.vertices().avg(laplace) - laplace(vh));
|
||||
|
||||
// update points by substracting the bi-laplacian damped by a factor of 0.5
|
||||
for (const auto& vh : mesh.vertices())
|
||||
points(vh) += -0.5 * bi_laplace(vh);
|
||||
}
|
||||
} // The laplace and update properties are removed from the mesh at the end of this scope.
|
||||
|
||||
// write mesh
|
||||
ok = OpenMesh::IO::write_mesh(mesh, "smoothed_smart_output.off");
|
||||
|
||||
EXPECT_TRUE(ok) << "Cannot write mesh to file 'smoothed_smart_output.off'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ LoadInfo open_progresult_mesh(const std::string& _filename)
|
||||
OpenMesh::IO::restore(ifs, vr, swap);
|
||||
|
||||
PMInfo pminfo;
|
||||
pminfo.p0 = p;
|
||||
pminfo.p0 = OpenMesh::vector_cast<Mesh::Point>(p);
|
||||
pminfo.v0 = result.mesh.add_vertex(p);
|
||||
pminfo.v1 = Mesh::VertexHandle(v1);
|
||||
pminfo.vl = Mesh::VertexHandle(vl);
|
||||
|
||||
@@ -263,6 +263,23 @@ TEST_F(OpenMeshVectorTest, BasicArithmeticImmutable) {
|
||||
EXPECT_NEAR(-2, v2neg[1], epsilon);
|
||||
EXPECT_NEAR(-3, v2neg[2], epsilon);
|
||||
}
|
||||
template <typename V1, typename V2, typename S>
|
||||
void test_dot(const V1 &v1, const V2 &v2, const S&s) {
|
||||
EXPECT_NEAR(s, v1 | v2, 1e-6);
|
||||
EXPECT_NEAR(s, v1.dot(v2), 1e-6);
|
||||
EXPECT_NEAR(-s, (-v1) | v2, 1e-6);
|
||||
EXPECT_NEAR(-s, (-v1).dot(v2), 1e-6);
|
||||
EXPECT_NEAR(s, v2 | v1, 1e-6);
|
||||
EXPECT_NEAR(s, v2.dot(v1), 1e-6);
|
||||
}
|
||||
|
||||
template <typename V1, typename V2, typename V3>
|
||||
void test_cross(const V1 &v1, const V2 &v2, const V3 &res) {
|
||||
EXPECT_NEAR(0, (v1.cross(v2) - res).norm(), 1e-6);
|
||||
EXPECT_NEAR(0, (v1 % v2 - res).norm(), 1e-6);
|
||||
EXPECT_NEAR(0, (v2.cross(v1) + res).norm(), 1e-6);
|
||||
EXPECT_NEAR(0, (v2 % v1 + res).norm(), 1e-6);
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshVectorTest, BasicLinearAlgebra) {
|
||||
OpenMesh::Vec3d v(1, 2, 3);
|
||||
@@ -285,9 +302,15 @@ TEST_F(OpenMeshVectorTest, BasicLinearAlgebra) {
|
||||
EXPECT_EQ(1, OpenMesh::Vec3d(1, 3, -4).min_abs());
|
||||
EXPECT_EQ(2, OpenMesh::Vec3d(-4, 2, 3).min_abs());
|
||||
|
||||
EXPECT_NEAR(14, OpenMesh::Vec3d(1, 2, 3) | OpenMesh::Vec3d(1, 2, 3), 1e-6);
|
||||
EXPECT_NEAR(-14, OpenMesh::Vec3d(1, 2, 3) | OpenMesh::Vec3d(-1, -2, -3), 1e-6);
|
||||
EXPECT_NEAR(14, OpenMesh::Vec3d(-1, -2, -3) | OpenMesh::Vec3d(-1, -2, -3), 1e-6);
|
||||
|
||||
test_dot(OpenMesh::Vec3d(1, 2, 3), OpenMesh::Vec3d(1, 2, 3), 14.);
|
||||
test_dot(OpenMesh::Vec3d(1, 2, 3), OpenMesh::Vec3d(-1, -2, -3), -14.);
|
||||
test_dot(OpenMesh::Vec3d(1, 2, 3), OpenMesh::Vec3i(1, 2, 3), 14);
|
||||
test_dot(OpenMesh::Vec3i(1, 2, 3), OpenMesh::Vec3i(1, 2, 3), 14);
|
||||
|
||||
test_cross(OpenMesh::Vec3i(2, 0, 0), OpenMesh::Vec3i(0, 3, 0), OpenMesh::Vec3i(0, 0, 6));
|
||||
test_cross(OpenMesh::Vec3d(2, 0, 0), OpenMesh::Vec3d(0, 3, 0), OpenMesh::Vec3d(0, 0, 6));
|
||||
test_cross(OpenMesh::Vec3d(2, 0, 0), OpenMesh::Vec3i(0, 3, 0), OpenMesh::Vec3d(0, 0, 6));
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshVectorTest, array_init) {
|
||||
@@ -397,4 +420,19 @@ TEST_F(OpenMeshVectorGCCBugTest, alignment_bug) {
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshVectorTest, Test_simple_0_constructor) {
|
||||
|
||||
// Create a test vector with zeroes from one parameter
|
||||
OpenMesh::Vec3d testVec = OpenMesh::Vec3d(0);
|
||||
|
||||
EXPECT_EQ(0.0f, testVec[0]) << "Wrong Value after construction!";
|
||||
EXPECT_EQ(0.0f, testVec[1]) << "Wrong Value after construction!";
|
||||
EXPECT_EQ(0.0f, testVec[2]) << "Wrong Value after construction!";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user