Commit 015efec1 authored by Johannes Lenzen's avatar Johannes Lenzen

Merge branch 'master' into 'docker-build-system'

# Conflicts:
#   CI/gitlab-ci/assemble-gitlab-ci.py
parents 0d6d85e3 8090f50b
Pipeline #13345 passed with stages
in 307 minutes and 47 seconds
......@@ -32,7 +32,7 @@ echo "CPPCHECK Summary"
echo "=============================================================================="
echo -e "${NC}"
MAX_COUNT=27
MAX_COUNT=23
if [ $COUNT -gt $MAX_COUNT ]; then
echo -e ${WARNING}
......
......@@ -4,6 +4,8 @@ import sys, os, re, yaml, hashlib
# Version 3.2
# Version 3
# Script for automated gitlab-ci creation
# Assembles the gitlab ci from master template file:
master_file = 'ci-master.yml'
......
......@@ -42,15 +42,15 @@ int main(int argc, char** argv)
for (const auto& vh : mesh.vertices())
laplace(vh) = vh.vertices().avg(points) - points(vh);
// Iterate over all vertices to compte update vectors as the negative of the laplace of the laplace damped by 0.5
// 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
// 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 is removed from the mesh at the end of this scope.
} // The laplace and update properties are removed from the mesh at the end of this scope.
// Write mesh file
......
......@@ -29,6 +29,7 @@
<ul>
<li>Subdivider: Fixed crash in Loop subdivider</li>
<li>Subdivider: Fixed crash in ModifiedButterfly subdivider</li>
<li>Decimater: Fixed ModNormalDeviationT not working for meshes with Eigen Vectors as vector type</li>
</ul>
......
......@@ -82,7 +82,7 @@ If, instead, a property is desired to survive its local scope, it should be crea
auto face_area = OpenMesh::FProp<double>(mesh, "face_area");
\endcode
At a later time, we can access the same property by using the same name. If we want to make sure, that we access a property that has already been created earler, we can use hasProperty() to test whether a mesh has the desired property:
At a later time, we can access the same property by using the same name. If we want to make sure, that we access a property that has already been created earlier, we can use hasProperty() to test whether a mesh has the desired property:
\code
if (OpenMesh::hasProperty<OpenMesh::FaceHandle, double>(mesh, "face_area")) {
// Property exists. Do something with it.
......
......@@ -60,6 +60,7 @@
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
//== NAMESPACES ===============================================================
......@@ -77,13 +78,14 @@ namespace OpenMesh {
the center normal and the opening angle.
**/
template <typename Scalar>
template <typename Vector>
class NormalConeT
{
public:
// typedefs
typedef VectorT<Scalar, 3> Vec3;
typedef typename vector_traits<Vector>::value_type Scalar;
typedef Vector Vec3;
//! default constructor (not initialized)
......
......@@ -70,8 +70,8 @@ namespace OpenMesh {
//== IMPLEMENTATION ==========================================================
template <typename Scalar>
NormalConeT<Scalar>::
template <typename Vector>
NormalConeT<Vector>::
NormalConeT(const Vec3& _center_normal, Scalar _angle)
: center_normal_(_center_normal), angle_(_angle)
{
......@@ -81,9 +81,9 @@ NormalConeT(const Vec3& _center_normal, Scalar _angle)
//----------------------------------------------------------------------------
template <typename Scalar>
Scalar
NormalConeT<Scalar>::
template <typename Vector>
typename NormalConeT<Vector>::Scalar
NormalConeT<Vector>::
max_angle(const Vec3& _norm) const
{
Scalar dotp = (center_normal_ | _norm);
......@@ -95,9 +95,9 @@ max_angle(const Vec3& _norm) const
//----------------------------------------------------------------------------
template <typename Scalar>
Scalar
NormalConeT<Scalar>::
template <typename Vector>
typename NormalConeT<Vector>::Scalar
NormalConeT<Vector>::
max_angle(const NormalConeT& _cone) const
{
Scalar dotp = (center_normal_ | _cone.center_normal_);
......@@ -112,12 +112,12 @@ max_angle(const NormalConeT& _cone) const
//----------------------------------------------------------------------------
template <typename Scalar>
template <typename Vector>
void
NormalConeT<Scalar>::
NormalConeT<Vector>::
merge(const NormalConeT& _cone)
{
Scalar dotp = (center_normal_ | _cone.center_normal_);
Scalar dotp = dot(center_normal_, _cone.center_normal_);
if (fabs(dotp) < 0.99999f)
{
......
......@@ -206,7 +206,6 @@ _OBJWriter_::
write(std::ostream& _out, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
unsigned int idx;
size_t nV, nF;
Vec3f v, n;
Vec2f t;
VertexHandle vh;
......
......@@ -40,11 +40,7 @@ bool _VTKWriter_::write(const std::string& _filename, BaseExporter& _be, Options
bool _VTKWriter_::write(std::ostream& _out, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
Vec3f n;
Vec2f t;
VertexHandle vh;
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
// check exporter features
if (!check(_be, _opt)) {
......
......@@ -766,7 +766,7 @@ public:
//! Complexity: O(1)
inline void erase(iterator _it)
{
assert(_it != end() && is_in(*_it));
assert(_it != const_cast<const ExtStatusSetT*>(this)->end() && is_in(*_it));
Base::erase(*_it);
*_it = handles_.back();
_it.pop_back();
......
......@@ -315,8 +315,6 @@ class GenericCirculatorT : protected GenericCirculatorBaseT<typename GenericCirc
/// Standard dereferencing operator.
smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = GenericCirculatorT_TraitsT::toHandle(this->mesh_, this->heh_);
......@@ -504,8 +502,6 @@ class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<typename
/// Standard dereferencing operator.
smart_value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = (GenericCirculatorT_DEPRECATED_TraitsT::toHandle(this->mesh_, this->heh_));
......
......@@ -59,7 +59,7 @@ namespace OpenMesh {
/// Base class for all handle types
class BaseHandle
class OPENMESHDLLEXPORT BaseHandle
{
public:
......@@ -117,35 +117,35 @@ inline std::ostream& operator<<(std::ostream& _os, const BaseHandle& _hnd)
/// Handle for a vertex entity
struct VertexHandle : public BaseHandle
struct OPENMESHDLLEXPORT VertexHandle : public BaseHandle
{
explicit VertexHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a halfedge entity
struct HalfedgeHandle : public BaseHandle
struct OPENMESHDLLEXPORT HalfedgeHandle : public BaseHandle
{
explicit HalfedgeHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a edge entity
struct EdgeHandle : public BaseHandle
struct OPENMESHDLLEXPORT EdgeHandle : public BaseHandle
{
explicit EdgeHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a face entity
struct FaceHandle : public BaseHandle
struct OPENMESHDLLEXPORT FaceHandle : public BaseHandle
{
explicit FaceHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle type for meshes to simplify some template programming
struct MeshHandle : public BaseHandle
struct OPENMESHDLLEXPORT MeshHandle : public BaseHandle
{
explicit MeshHandle(int _idx=-1) : BaseHandle(_idx) {}
};
......
......@@ -271,14 +271,33 @@ public:
/** Calculate normal vector for face (_p0, _p1, _p2). */
Normal calc_face_normal(const Point& _p0, const Point& _p1,
const Point& _p2) const;
/// same as calc_face_normal
Normal calc_normal(FaceHandle _fh) const;
/// calculates the average of the vertices defining _fh
void calc_face_centroid(FaceHandle _fh, Point& _pt) const {
_pt = calc_face_centroid(_fh);
}
/// Computes and returns the average of the vertices defining _gh
/// Computes and returns the average of the vertices defining _fh
Point calc_face_centroid(FaceHandle _fh) const;
/// Computes and returns the average of the vertices defining _fh (same as calc_face_centroid)
Point calc_centroid(FaceHandle _fh) const;
/// Computes and returns the average of the vertices defining _eh (same as calc_edge_midpoint)
Point calc_centroid(EdgeHandle _eh) const;
/// Computes and returns the average of the vertices defining _heh (same as calc_edge_midpoint for edge of halfedge)
Point calc_centroid(HalfedgeHandle _heh) const;
/// Returns the point of _vh
Point calc_centroid(VertexHandle _vh) const;
/// Computes and returns the average of the vertices defining the mesh
Point calc_centroid(MeshHandle _mh) const;
/// Update normal for halfedge _heh
void update_normal(HalfedgeHandle _heh, const double _feature_angle = 0.8)
{ this->set_normal(_heh, calc_halfedge_normal(_heh,_feature_angle)); }
......@@ -308,6 +327,8 @@ public:
*/
virtual Normal calc_halfedge_normal(HalfedgeHandle _heh, const double _feature_angle = 0.8) const;
/// same as calc_halfedge_normal
Normal calc_normal(HalfedgeHandle, const double _feature_angle = 0.8) const;
/** identifies feature edges w.r.t. the minimal dihedral angle for feature edges (in radians) */
/** and the status feature tag */
......@@ -353,6 +374,8 @@ public:
void calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const;
void calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const;
/// same as calc_vertex_normal_correct
Normal calc_normal(VertexHandle _vh) const;
//@}
......@@ -422,6 +445,15 @@ public:
return calc_edge_midpoint(this->halfedge_handle(_eh, 0));
}
/// calculated and returns the average of the two vertex normals
Normal calc_normal(EdgeHandle _eh) const
{
HalfedgeHandle _heh = this->halfedge_handle(_eh, 0);
VertexHandle vh0 = this->from_vertex_handle(_heh);
VertexHandle vh1 = this->to_vertex_handle(_heh);
return 0.5 * (this->calc_normal(vh0) + this->calc_normal(vh1));
}
/** defines a consistent representation of a sector geometry:
the halfedge _in_heh defines the sector orientation
the vertex pointed by _in_heh defines the sector center
......
......@@ -181,6 +181,14 @@ calc_face_normal(const Point& _p0,
>::Result());
}
template<class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_normal(FaceHandle _fh) const
{
return calc_face_normal(_fh);
}
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
......@@ -250,8 +258,58 @@ calc_face_centroid(FaceHandle _fh) const
_pt /= valence;
return _pt;
}
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_centroid(FaceHandle _fh) const
{
return calc_face_centroid(_fh);
}
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_centroid(EdgeHandle _eh) const
{
return this->calc_edge_midpoint(_eh);
}
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_centroid(HalfedgeHandle _heh) const
{
return this->calc_edge_midpoint(this->edge_handle(_heh));
}
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_centroid(VertexHandle _vh) const
{
return this->point(_vh);
}
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_centroid(MeshHandle /*_mh*/) const
{
return this->vertices().avg(getPointsProperty(*this));
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
......@@ -354,6 +412,18 @@ calc_halfedge_normal(HalfedgeHandle _heh, const double _feature_angle) const
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_normal(HalfedgeHandle _heh, const double _feature_angle) const
{
return calc_halfedge_normal(_heh, _feature_angle);
}
//-----------------------------------------------------------------------------
template <class Kernel>
bool
PolyMeshT<Kernel>::
......@@ -435,6 +505,9 @@ calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const
in_he_vec = out_he_vec;
in_he_vec *= -1;//change the orientation
}
Scalar length = norm(_n);
if (length != 0.0)
_n *= (Scalar(1.0)/length);
}
//-----------------------------------------------------------------------------
......@@ -459,6 +532,17 @@ calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const
//-----------------------------------------------------------------------------
template<class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_normal(VertexHandle _vh) const
{
Normal n;
calc_vertex_normal_correct(_vh, n);
return n;
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
......
......@@ -78,18 +78,18 @@ struct SmartRangeT
* @param f Functor that is applied to all elements before computing the sum
*/
template <typename Functor>
auto sum(Functor&& f) -> decltype (f(std::declval<HandleT>())+f(std::declval<HandleT>()))
auto sum(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
{
auto range = static_cast<const RangeT*>(this);
auto begin = range->begin();
auto end = range->end();
assert(begin != end);
decltype (f(*begin) + f(*begin)) sum = f(*begin);
typename std::decay<decltype (f(*begin))>::type result = f(*begin);
auto it = begin;
++it;
for (; it != end; ++it)
sum += f(*it);
return sum;
result += f(*it);
return result;
}
/** @brief Computes the average of elements.
......@@ -99,22 +99,22 @@ struct SmartRangeT
* @param f Functor that is applied to all elements before computing the average.
*/
template <typename Functor>
auto avg(Functor&& f) -> decltype (1.0 * (f(std::declval<HandleT>())+f(std::declval<HandleT>())))
auto avg(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
{
auto range = static_cast<const RangeT*>(this);
auto begin = range->begin();
auto end = range->end();
assert(begin != end);
decltype (f(*begin) + f(*begin)) sum = f(*begin);
typename std::decay<decltype (f(*begin))>::type result = f(*begin);
auto it = begin;
++it;
int n_elements = 1;
for (; it != end; ++it)
{
sum += f(*it);
result += f(*it);
++n_elements;
}
return (1.0 / n_elements) * sum;
return (1.0 / n_elements) * result;
}
/** @brief Check if any element fulfils condition.
......@@ -161,10 +161,10 @@ struct SmartRangeT
* the array will contain the handles.
*/
template <int n, typename Functor = Identity>
auto to_array(Functor&& f = {}) -> std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type, n>
auto to_array(Functor&& f = {}) -> std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n>
{
auto range = static_cast<const RangeT*>(this);
std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type, n> res;
std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n> res;
auto it = range->begin();
auto end = range->end();
int i = 0;
......@@ -181,10 +181,10 @@ struct SmartRangeT
* the vector will contain the handles.
*/
template <typename Functor = Identity>
auto to_vector(Functor&& f = {}) -> std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
auto to_vector(Functor&& f = {}) -> std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
{
auto range = static_cast<const RangeT*>(this);
std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type> res;
std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
for (const auto& e : *range)
res.push_back(f(e));
return res;
......@@ -198,10 +198,10 @@ struct SmartRangeT
* the set will contain the handles.
*/
template <typename Functor = Identity>
auto to_set(Functor&& f = {}) -> std::set<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
auto to_set(Functor&& f = {}) -> std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
{
auto range = static_cast<const RangeT*>(this);
std::set<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type> res;
std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
for (const auto& e : *range)
res.insert(f(e));
return res;
......@@ -232,7 +232,7 @@ struct SmartRangeT
* @param f Functor that is applied to all elements before computing minimum.
*/
template <typename Functor>
auto min(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
auto min(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
{
using std::min;
......@@ -241,7 +241,7 @@ struct SmartRangeT
auto end = range->end();
assert(it != end);
typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
++it;
for (; it != end; ++it)
......@@ -257,7 +257,7 @@ struct SmartRangeT
* @param f Functor that is applied to all elements before computing maximum.
*/
template <typename Functor>
auto max(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
auto max(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
{
using std::max;
......@@ -266,7 +266,7 @@ struct SmartRangeT
auto end = range->end();
assert(it != end);
typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
++it;
for (; it != end; ++it)
......@@ -283,8 +283,8 @@ struct SmartRangeT
* @param f Functor that is applied to all elements before computing maximum.
*/
template <typename Functor>
auto minmax(Functor&& f) -> std::pair<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type,
typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
auto minmax(Functor&& f) -> std::pair<typename std::decay<decltype (f(std::declval<HandleT>()))>::type,
typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
{
return std::make_pair(this->min(f), this->max(f));
}
......
......@@ -35,6 +35,11 @@ namespace OpenMesh {
using type = OpenMesh::MPropHandleT<T>;
};
template<typename T>
struct HandleToPropHandle<OpenMesh::MeshHandle, T> {
using type = OpenMesh::MPropHandleT<T>;
};
} // namespace OpenMesh
#endif // HANDLETOPROPHANDLE_HH_
\ No newline at end of file
#endif // HANDLETOPROPHANDLE_HH_
......@@ -297,9 +297,9 @@ class PropertyManager {
*
*/
template <typename MeshType >
const MeshType& getMesh() const { return dynamic_cast<MeshType&>(mesh_); }
const MeshType& getMesh() const { return dynamic_cast<const MeshType&>(mesh_); }
const MeshT& getMesh() const { return dynamic_cast<MeshT&>(mesh_); }
const MeshT& getMesh() const { return dynamic_cast<const MeshT&>(mesh_); }
/**
......
......@@ -133,16 +133,16 @@ template<class MeshT>
float ModAspectRatioT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
typename Mesh::VertexHandle v2, v3;
typename Mesh::FaceHandle fh;
const typename Mesh::Point *p1(&_ci.p1), *p2, *p3;
const typename Mesh::Point* p1(&_ci.p1);
typename Mesh::Scalar r0, r1, r0_min(1.0), r1_min(1.0);
typename Mesh::ConstVertexOHalfedgeIter voh_it(mesh_, _ci.v0);
v3 = mesh_.to_vertex_handle(*voh_it);
p3 = &mesh_.point(v3);
auto p3 = &mesh_.point(v3);
while (voh_it.is_valid()) {
v2 = v3;
p2 = p3;
auto p2 = p3;
++voh_it;
v3 = mesh_.to_vertex_handle(*voh_it);
......
......@@ -97,7 +97,7 @@ public:
typedef typename Mesh::VertexHandle VertexHandle;
typedef typename Mesh::FaceHandle FaceHandle;
typedef typename Mesh::EdgeHandle EdgeHandle;
typedef NormalConeT<Scalar> NormalCone;
typedef NormalConeT<Normal> NormalCone;
......
......@@ -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!";
......
......@@ -7,6 +7,9 @@
#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>
......@@ -232,6 +235,37 @@ TEST_F(OpenMeshEigenTest, LoadSimpleOFFFile) {
mesh_.update_normals();