From c2731d1b4d2615c6e4d4ce80af3b546a507377c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Mon, 7 Nov 2011 07:18:15 +0000 Subject: [PATCH] Don't depend on ACG git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@451 fdac6126-5c0c-442c-9429-916003d36597 --- .../Tools/Decimater/ModEdgeLengthT.cc | 3 +- src/OpenMesh/Tools/Decimater/ModHausdorffT.cc | 134 +++++++++++++++++- src/OpenMesh/Tools/Decimater/ModHausdorffT.hh | 10 ++ 3 files changed, 139 insertions(+), 8 deletions(-) diff --git a/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc index 1082900b..4c0a69c6 100644 --- a/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc +++ b/src/OpenMesh/Tools/Decimater/ModEdgeLengthT.cc @@ -54,8 +54,7 @@ //== INCLUDES ================================================================= -#include "ModEdgeLengthT.hh" -#include +#include "ModEdgeLengthT.hh"s //== NAMESPACES =============================================================== diff --git a/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc b/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc index 99b94a2c..9058201d 100644 --- a/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc +++ b/src/OpenMesh/Tools/Decimater/ModHausdorffT.cc @@ -55,7 +55,6 @@ //== INCLUDES ================================================================= #include "ModHausdorffT.hh" -#include //== NAMESPACES =============================================================== @@ -63,10 +62,133 @@ namespace OpenMesh { namespace Decimater { - //== IMPLEMENTATION ========================================================== +template +typename Vec::value_type +distPointTriangleSquared( const Vec& _p, + const Vec& _v0, + const Vec& _v1, + const Vec& _v2, + Vec& _nearestPoint ) +{ + Vec v0v1 = _v1 - _v0; + Vec v0v2 = _v2 - _v0; + Vec n = v0v1 % v0v2; // not normalized ! + double d = n.sqrnorm(); + + + // Check if the triangle is degenerated + if (d < FLT_MIN && d > -FLT_MIN) { + std::cerr << "distPointTriangleSquared: Degenerated triangle !\n"; + return -1.0; + } + double invD = 1.0 / d; + + + // these are not needed for every point, should still perform + // better with many points against one triangle + Vec v1v2 = _v2 - _v1; + double inv_v0v2_2 = 1.0 / v0v2.sqrnorm(); + double inv_v0v1_2 = 1.0 / v0v1.sqrnorm(); + double inv_v1v2_2 = 1.0 / v1v2.sqrnorm(); + + + Vec v0p = _p - _v0; + Vec t = v0p % n; + double s01, s02, s12; + double a = (t | v0v2) * -invD; + double b = (t | v0v1) * invD; + + + if (a < 0) + { + // Calculate the distance to an edge or a corner vertex + s02 = ( v0v2 | v0p ) * inv_v0v2_2; + if (s02 < 0.0) + { + s01 = ( v0v1 | v0p ) * inv_v0v1_2; + if (s01 <= 0.0) { + v0p = _v0; + } else if (s01 >= 1.0) { + v0p = _v1; + } else { + v0p = _v0 + v0v1 * s01; + } + } else if (s02 > 1.0) { + s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2; + if (s12 >= 1.0) { + v0p = _v2; + } else if (s12 <= 0.0) { + v0p = _v1; + } else { + v0p = _v1 + v1v2 * s12; + } + } else { + v0p = _v0 + v0v2 * s02; + } + } else if (b < 0.0) { + // Calculate the distance to an edge or a corner vertex + s01 = ( v0v1 | v0p ) * inv_v0v1_2; + if (s01 < 0.0) + { + s02 = ( v0v2 | v0p ) * inv_v0v2_2; + if (s02 <= 0.0) { + v0p = _v0; + } else if (s02 >= 1.0) { + v0p = _v2; + } else { + v0p = _v0 + v0v2 * s02; + } + } else if (s01 > 1.0) { + s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2; + if (s12 >= 1.0) { + v0p = _v2; + } else if (s12 <= 0.0) { + v0p = _v1; + } else { + v0p = _v1 + v1v2 * s12; + } + } else { + v0p = _v0 + v0v1 * s01; + } + } else if (a+b > 1.0) { + // Calculate the distance to an edge or a corner vertex + s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2; + if (s12 >= 1.0) { + s02 = ( v0v2 | v0p ) * inv_v0v2_2; + if (s02 <= 0.0) { + v0p = _v0; + } else if (s02 >= 1.0) { + v0p = _v2; + } else { + v0p = _v0 + v0v2*s02; + } + } else if (s12 <= 0.0) { + s01 = ( v0v1 | v0p ) * inv_v0v1_2; + if (s01 <= 0.0) { + v0p = _v0; + } else if (s01 >= 1.0) { + v0p = _v1; + } else { + v0p = _v0 + v0v1 * s01; + } + } else { + v0p = _v1 + v1v2 * s12; + } + } else { + // Calculate the distance to an interior point of the triangle + _nearestPoint = _p - n*((n|v0p) * invD); + return (_nearestPoint - _p).sqrnorm(); + } + + _nearestPoint = v0p; + + return (_nearestPoint - _p).sqrnorm(); +} + + template void ModHausdorffT:: @@ -136,7 +258,7 @@ collapse_priority(const CollapseInfo& _ci) 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) + if ( distPointTriangleSquared(*p_it, p0, p1, p2, dummy) <= sqr_tolerace) ok = true; } } @@ -222,7 +344,7 @@ postprocess_collapse(const CollapseInfo& _ci) const Point& p1 = mesh_.point(++fv_it); const Point& p2 = mesh_.point(++fv_it); - e = ACG::Geometry::distPointTriangleSquared(*p_it, p0, p1, p2, dummy); + e = distPointTriangleSquared(*p_it, p0, p1, p2, dummy); if (e < emin) { emin = e; fh = *fh_it; @@ -254,10 +376,10 @@ compute_sqr_error(FaceHandle _fh, const Point& _p) const Point dummy; Scalar e; - Scalar emax = ACG::Geometry::distPointTriangleSquared(_p, p0, p1, p2, dummy); + Scalar emax = distPointTriangleSquared(_p, p0, p1, p2, dummy); for (; p_it!=p_end; ++p_it) { - e = ACG::Geometry::distPointTriangleSquared(*p_it, p0, p1, p2, dummy); + e = distPointTriangleSquared(*p_it, p0, p1, p2, dummy); if (e > emax) emax = e; } diff --git a/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh b/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh index 9aeca3ea..98aed219 100644 --- a/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh +++ b/src/OpenMesh/Tools/Decimater/ModHausdorffT.hh @@ -124,6 +124,16 @@ public: private: + /// squared distance from point _p to triangle (_v0, _v1, _v2) + template + typename Vec::value_type + distPointTriangleSquared( const Vec& _p, + const Vec& _v0, + const Vec& _v1, + const Vec& _v2, + Vec& _nearestPoint ); + + /// compute max error for face _fh w.r.t. its point list and _p Scalar compute_sqr_error(FaceHandle _fh, const Point& _p) const; -- GitLab