diff --git a/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc new file mode 100644 index 00000000..1082900b --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc @@ -0,0 +1,99 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of * + * the License, or (at your option) any later version with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision: 448 $ * + * $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ * + * * +\*===========================================================================*/ + +/** \file ModEdgeLengthT.cc + */ + + +//============================================================================= +// +// CLASS ModEdgeLengthT - IMPLEMENTATION +// +//============================================================================= + +#define MB_MODEDGELENGTHT_C + + +//== INCLUDES ================================================================= + +#include "ModEdgeLengthT.hh" +#include + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { +namespace Decimater { + + +//== IMPLEMENTATION ========================================================== + + +template +ModEdgeLengthT:: +ModEdgeLengthT(DecimaterT &_dec, float _edge_length, bool _is_binary) + : Base(_dec, _is_binary), + mesh_(Base::mesh()) +{ + set_edge_length(_edge_length); +} + + +//----------------------------------------------------------------------------- + + +template +float +ModEdgeLengthT:: +collapse_priority(const CollapseInfo& _ci) +{ + typename Mesh::Scalar sqr_length = (_ci.p0 - _ci.p1).sqrnorm(); + + return ((sqr_length <= sqr_edge_length_) ? + sqr_length : + float( Base::ILLEGAL_COLLAPSE )); +} + + +//============================================================================= +} +} +//============================================================================= diff --git a/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.hh b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.hh new file mode 100644 index 00000000..5362ffc6 --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.hh @@ -0,0 +1,118 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of * + * the License, or (at your option) any later version with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision: 448 $ * + * $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ * + * * +\*===========================================================================*/ + +/** \file ModEdgeLengthT.hh + */ + +//============================================================================= +// +// CLASS ModEdgeLengthT +// +//============================================================================= + + +#ifndef MB_MODEDGELENGTHT_HH +#define MB_MODEDGELENGTHT_HH + + +//== INCLUDES ================================================================= + +#include +#include + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { +namespace Decimater { + + +//== CLASS DEFINITION ========================================================= + + +template +class ModEdgeLengthT : public ModBaseT +{ +public: + + DECIMATING_MODULE( ModEdgeLengthT, DecimaterT, EdgeLength ); + + /// Constructor + ModEdgeLengthT(DecimaterT& _dec, + float _edge_length = FLT_MAX, + bool _is_binary = true); + + + /// get edge_length + float edge_length() const { return edge_length_; } + + /// set edge_length + void set_edge_length(float _f) + { edge_length_ = _f; sqr_edge_length_ = _f*_f; } + + + /** Compute priority: + Binary mode: Don't collapse edges longer then edge_length_ + Cont. mode: Collapse smallest edge first, but + don't collapse edges longer as edge_length_ + */ + float collapse_priority(const CollapseInfo& _ci); + + +private: + + Mesh& mesh_; + typename Mesh::Scalar edge_length_, sqr_edge_length_; +}; + + +//============================================================================= +} // END_NS_DECIMATER +} // END_NS_OPENMESH +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(MB_MODEDGELENGTHT_C) +#define MB_MODEDGELENGTHT_TEMPLATES +#include "ModEdgeLengthT.cc" +#endif +//============================================================================= +#endif // MB_MODEDGELENGTHT_HH defined +//============================================================================= + diff --git a/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc b/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc new file mode 100644 index 00000000..99b94a2c --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc @@ -0,0 +1,272 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of * + * the License, or (at your option) any later version with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision: 448 $ * + * $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ * + * * +\*===========================================================================*/ + +/** \file ModHausdorffT.cc + */ + + +//============================================================================= +// +// CLASS ModHausdorffT - IMPLEMENTATION +// +//============================================================================= + +#define MB_MODHAUSDORFFT_C + + +//== INCLUDES ================================================================= + +#include "ModHausdorffT.hh" +#include + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { +namespace Decimater { + + +//== IMPLEMENTATION ========================================================== + + +template +void +ModHausdorffT:: +initialize() +{ + typename Mesh::FIter f_it(mesh_.faces_begin()), f_end(mesh_.faces_end()); + + for (; f_it!=f_end; ++f_it) + mesh_.property(points_, f_it).clear(); +} + + +//----------------------------------------------------------------------------- + + +template +float +ModHausdorffT:: +collapse_priority(const CollapseInfo& _ci) +{ + static Points points; points.clear(); + std::vector faces; faces.reserve(20); + typename Mesh::VertexFaceIter vf_it; + typename Mesh::FaceHandle fh; + typename Mesh::Scalar sqr_tolerace = tolerance_*tolerance_; + typename Mesh::Point dummy; + typename Mesh::CFVIter fv_it; + bool ok; + + + + // collect all points to be tested + // collect all faces to be tested against + for (vf_it=mesh_.vf_iter(_ci.v0); vf_it; ++vf_it) { + fh = vf_it.handle(); + + if (fh != _ci.fl && fh != _ci.fr) + faces.push_back(fh); + + Points& pts = mesh_.property(points_, fh); + std::copy(pts.begin(), pts.end(), std::back_inserter(points)); + } + + + // add point to be removed + points.push_back(_ci.p0); + + + // setup iterators + typename std::vector::iterator fh_it, fh_end(faces.end()); + typename Points::const_iterator p_it, p_end(points.end()); + + + + // simulate collapse + mesh_.set_point(_ci.v0, _ci.p1); + + + + // for each point: try to find a face such that error is < tolerance + ok = true; + for (p_it=points.begin(); ok && p_it!=p_end; ++p_it) { + ok = false; + + for (fh_it=faces.begin(); !ok && fh_it!=fh_end; ++fh_it) { + const Point& p0 = mesh_.point(fv_it=mesh_.cfv_iter(*fh_it)); + const Point& p1 = mesh_.point(++fv_it); + const Point& p2 = mesh_.point(++fv_it); + + if ( ACG::Geometry::distPointTriangleSquared(*p_it, p0, p1, p2, dummy) <= sqr_tolerace) + ok = true; + } + } + + + + // undo simulation changes + mesh_.set_point(_ci.v0, _ci.p0); + + + + return ( ok ? Base::LEGAL_COLLAPSE : Base::ILLEGAL_COLLAPSE ); +} + + +//----------------------------------------------------------------------------- + + +template +void +ModHausdorffT:: +postprocess_collapse(const CollapseInfo& _ci) +{ + static Points points; + typename Mesh::VertexFaceIter vf_it; + FaceHandle fh; + std::vector faces; + + + // collect points & neighboring triangles + + points.clear(); // it's static ! + faces.reserve(20); + + + // collect active faces and their points + for (vf_it=mesh_.vf_iter(_ci.v1); vf_it; ++vf_it) { + fh = vf_it.handle(); + faces.push_back(fh); + + Points& pts = mesh_.property(points_, fh); + std::copy(pts.begin(), pts.end(), std::back_inserter(points)); + pts.clear(); + } + if (faces.empty()) return; // should not happen anyway... + + + // collect points of the 2 deleted faces + if ((fh=_ci.fl).is_valid()) { + Points& pts = mesh_.property(points_, fh); + std::copy(pts.begin(), pts.end(), std::back_inserter(points)); + pts.clear(); + } + if ((fh=_ci.fr).is_valid()) { + Points& pts = mesh_.property(points_, fh); + std::copy(pts.begin(), pts.end(), std::back_inserter(points)); + pts.clear(); + } + + + // add the deleted point + points.push_back(_ci.p0); + + + + + // setup iterators + typename std::vector::iterator fh_it, fh_end(faces.end()); + typename Points::const_iterator p_it, p_end(points.end()); + + + + // re-distribute points + Scalar emin, e; + Point dummy; + typename Mesh::CFVIter fv_it; + + for (p_it=points.begin(); p_it!=p_end; ++p_it) { + emin = FLT_MAX; + + for (fh_it=faces.begin(); fh_it!=fh_end; ++fh_it) { + const Point& p0 = mesh_.point(fv_it=mesh_.cfv_iter(*fh_it)); + const Point& p1 = mesh_.point(++fv_it); + const Point& p2 = mesh_.point(++fv_it); + + e = ACG::Geometry::distPointTriangleSquared(*p_it, p0, p1, p2, dummy); + if (e < emin) { + emin = e; + fh = *fh_it; + } + + } + + mesh_.property(points_, fh).push_back(*p_it); + } +} + + +//----------------------------------------------------------------------------- + + +template +typename ModHausdorffT::Scalar +ModHausdorffT:: +compute_sqr_error(FaceHandle _fh, const Point& _p) const +{ + typename Mesh::CFVIter fv_it = mesh_.cfv_iter(_fh); + const Point& p0 = mesh_.point(fv_it); + const Point& p1 = mesh_.point(++fv_it); + const Point& p2 = mesh_.point(++fv_it); + + const Points& points = mesh_.property(points_, _fh); + typename Points::const_iterator p_it = points.begin(); + typename Points::const_iterator p_end = points.end(); + + Point dummy; + Scalar e; + Scalar emax = ACG::Geometry::distPointTriangleSquared(_p, p0, p1, p2, dummy); + + for (; p_it!=p_end; ++p_it) { + e = ACG::Geometry::distPointTriangleSquared(*p_it, p0, p1, p2, dummy); + if (e > emax) + emax = e; + } + + return emax; +} + + +//============================================================================= +} +} +//============================================================================= diff --git a/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh b/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh new file mode 100644 index 00000000..9aeca3ea --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh @@ -0,0 +1,151 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of * + * the License, or (at your option) any later version with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision: 448 $ * + * $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ * + * * +\*===========================================================================*/ + +/** \file ModHausdorffT.hh + */ + + +//============================================================================= +// +// CLASS ModHausdorffT +// +//============================================================================= + + +#ifndef MB_MODHAUSDORFFT_HH +#define MB_MODHAUSDORFFT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { +namespace Decimater { + + +//== CLASS DEFINITION ========================================================= + + +template +class ModHausdorffT : public ModBaseT +{ +public: + + DECIMATING_MODULE( ModHausdorffT, DecimaterT, Roundness ); + + typedef typename Mesh::Scalar Scalar; + typedef typename Mesh::Point Point; + typedef typename Mesh::FaceHandle FaceHandle; + typedef std::vector Points; + + + /// Constructor + ModHausdorffT(DecimaterT& _dec, + Scalar _error_tolerance = FLT_MAX) + : Base(_dec, true), + mesh_(Base::mesh()), + tolerance_(_error_tolerance) + { + mesh_.add_property(points_); + } + + + /// Destructor + ~ModHausdorffT() + { + mesh_.remove_property(points_); + } + + + /// get max error tolerance + Scalar tolerance() const { return tolerance_; } + + /// set max error tolerance + void set_tolerance(Scalar _e) { tolerance_ = _e; } + + + /// reset per-face point lists + virtual void initialize(); + + + /// compute Hausdorff error for one-ring + virtual float collapse_priority(const CollapseInfo& _ci); + + + /// re-distribute points + virtual void postprocess_collapse(const CollapseInfo& _ci); + + + +private: + + /// compute max error for face _fh w.r.t. its point list and _p + Scalar compute_sqr_error(FaceHandle _fh, const Point& _p) const; + + +private: + + Mesh& mesh_; + Scalar tolerance_; + + OpenMesh::FPropHandleT points_; +}; + + +//============================================================================= +} // END_NS_DECIMATER +} // END_NS_OPENMESH +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(MB_MODHAUSDORFFT_C) +#define MB_MODHAUSDORFFT_TEMPLATES +#include "ModHausdorffT.cc" +#endif +//============================================================================= +#endif // MB_MODHAUSDORFFT_HH defined +//============================================================================= + diff --git a/src/OpenMesh/Tools/Decimater/ModNormalDeviationT.hh b/src/OpenMesh/Tools/Decimater/ModNormalDeviationT.hh new file mode 100644 index 00000000..497ec52d --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/ModNormalDeviationT.hh @@ -0,0 +1,213 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * This file is part of OpenMesh. * + * * + * OpenMesh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of * + * the License, or (at your option) any later version with the * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision: 448 $ * + * $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ * + * * +\*===========================================================================*/ + +/** \file ModNormalDeviationT.hh + */ + +//============================================================================= +// +// CLASS ModNormalDeviationT +// +//============================================================================= + + +#ifndef MB_MODNORMALDEVIATIONT_HH +#define MB_MODNORMALDEVIATIONT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { +namespace Decimater { + + +//== CLASS DEFINITION ========================================================= + + + +template +class ModNormalDeviationT : public ModBaseT< DecimaterT > +{ +public: + + DECIMATING_MODULE( ModNormalDeviationT, DecimaterT, NormalDeviation ); + + typedef typename Mesh::Scalar Scalar; + typedef typename Mesh::Point Point; + typedef typename Mesh::Normal Normal; + typedef typename Mesh::VertexHandle VertexHandle; + typedef typename Mesh::FaceHandle FaceHandle; + typedef typename Mesh::EdgeHandle EdgeHandle; + typedef ACG::Geometry::NormalConeT NormalCone; + + + +public: + + /// Constructor + ModNormalDeviationT(DecimaterT& _dec, float _max_dev = 180.0) + : Base(_dec, true), + mesh_(Base::mesh()) + { + set_normal_deviation(_max_dev); + mesh_.add_property(normal_cones_); + } + + + /// Destructor + ~ModNormalDeviationT() { + mesh_.add_property(normal_cones_); + } + + + /// Get normal deviation + Scalar normal_deviation() const { + return normal_deviation_ / M_PI * 180.0; + } + + /// Set normal deviation + void set_normal_deviation(Scalar _s) { + normal_deviation_ = _s / 180.0 * M_PI; + } + + + /// Allocate and init normal cones + void initialize() { + if (!normal_cones_.is_valid()) + mesh_.add_property(normal_cones_); + + typename Mesh::FaceIter f_it = mesh_.faces_begin(), + f_end = mesh_.faces_end(); + + for (; f_it != f_end; ++f_it) + mesh_.property(normal_cones_, f_it) = NormalCone(mesh_.normal(f_it)); + } + + + float collapse_priority(const CollapseInfo& _ci) { + // simulate collapse + mesh_.set_point(_ci.v0, _ci.p1); + + + typename Mesh::Scalar max_angle(0.0); + typename Mesh::ConstVertexFaceIter vf_it(mesh_, _ci.v0); + typename Mesh::FaceHandle fh, fhl, fhr; + + if (_ci.v0vl.is_valid()) fhl = mesh_.face_handle(_ci.v0vl); + if (_ci.vrv0.is_valid()) fhr = mesh_.face_handle(_ci.vrv0); + + for (; vf_it; ++vf_it) { + fh = vf_it.handle(); + if (fh != _ci.fl && fh != _ci.fr) { + NormalCone nc = mesh_.property(normal_cones_, fh); + + nc.merge(NormalCone(mesh_.calc_face_normal(fh))); + if (fh == fhl) nc.merge(mesh_.property(normal_cones_, _ci.fl)); + if (fh == fhr) nc.merge(mesh_.property(normal_cones_, _ci.fr)); + + if (nc.angle() > max_angle) { + max_angle = nc.angle(); + if (max_angle > 0.5*normal_deviation_) + break; + } + } + } + + + // undo simulation changes + mesh_.set_point(_ci.v0, _ci.p0); + + + return (max_angle < 0.5*normal_deviation_ ? + max_angle : float( Base::ILLEGAL_COLLAPSE )); + } + + + void postprocess_collapse(const CollapseInfo& _ci) { + // account for changed normals + typename Mesh::VertexFaceIter vf_it(mesh_, _ci.v1); + for (; vf_it; ++vf_it) + mesh_.property(normal_cones_, vf_it). + merge(NormalCone(mesh_.normal(vf_it))); + + + // normal cones of deleted triangles + typename Mesh::FaceHandle fh; + + if (_ci.vlv1.is_valid()) { + fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(_ci.vlv1)); + if (fh.is_valid()) + mesh_.property(normal_cones_, fh). + merge(mesh_.property(normal_cones_, _ci.fl)); + } + + if (_ci.v1vr.is_valid()) { + fh = mesh_.face_handle(mesh_.opposite_halfedge_handle(_ci.v1vr)); + if (fh.is_valid()) + mesh_.property(normal_cones_, fh). + merge(mesh_.property(normal_cones_, _ci.fr)); + } + } + + + +private: + + Mesh& mesh_; + Scalar normal_deviation_; + OpenMesh::FPropHandleT normal_cones_; +}; + + +//============================================================================= +} // END_NS_DECIMATER +} // END_NS_OPENMESH +//============================================================================= +#endif // MB_MODNORMALDEVIATIONT_HH defined +//============================================================================= +