OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*===========================================================================*/ 00034 00035 /*===========================================================================*\ 00036 * * 00037 * $Revision: 460 $ * 00038 * $Date: 2011-11-16 10:45:08 +0100 (Mi, 16 Nov 2011) $ * 00039 * * 00040 \*===========================================================================*/ 00041 00046 //============================================================================= 00047 // 00048 // CLASS ModRoundnessT 00049 // 00050 //============================================================================= 00051 00052 #ifndef OPENMESH_DECIMATER_MODROUNDNESST_HH 00053 #define OPENMESH_DECIMATER_MODROUNDNESST_HH 00054 00055 00056 //== INCLUDES ================================================================= 00057 00058 #include <OpenMesh/Tools/Decimater/ModBaseT.hh> 00059 #include <math.h> 00060 00061 #if defined(OM_CC_MSVC) 00062 # define OM_ENABLE_WARNINGS 4244 00063 # pragma warning(disable : OM_ENABLE_WARNINGS ) 00064 #endif 00065 00066 //== NAMESPACE ================================================================ 00067 00068 namespace OpenMesh { // BEGIN_NS_OPENMESH 00069 namespace Decimater { // BEGIN_NS_DECIMATER 00070 00071 00072 //== CLASS DEFINITION ========================================================= 00073 00074 00083 template <class DecimaterType> 00084 class ModRoundnessT : public ModBaseT<DecimaterType> 00085 { 00086 public: 00087 DECIMATING_MODULE( ModRoundnessT, DecimaterType, Roundness ); 00088 00089 public: 00090 00091 // typedefs 00092 typedef typename Mesh::Point Point; 00093 typedef typename vector_traits<Point>::value_type value_type; 00094 00095 public: 00096 00098 ModRoundnessT( DecimaterType &_dec ) : 00099 Base(_dec, false), 00100 min_r_(-1.0) 00101 { } 00102 00104 ~ModRoundnessT() { } 00105 00106 public: // inherited 00107 00118 float collapse_priority(const CollapseInfo& _ci) 00119 { 00120 // using namespace OpenMesh; 00121 00122 typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0); 00123 double r; 00124 double priority = 0.0; //==LEGAL_COLLAPSE 00125 typename Mesh::FaceHandle fhC, fhB; 00126 Vec3f B,C; 00127 00128 if ( min_r_ < 0.0 ) // continues mode 00129 { 00130 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it))); 00131 fhC = Base::mesh().face_handle( voh_it.handle() ); 00132 00133 for (++voh_it; voh_it; ++voh_it) 00134 { 00135 B = C; 00136 fhB = fhC; 00137 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it))); 00138 fhC = Base::mesh().face_handle( voh_it.handle() ); 00139 00140 if ( fhB == _ci.fl || fhB == _ci.fr ) 00141 continue; 00142 00143 // simulate collapse using position of v1 00144 r = roundness( vector_cast<Vec3f>(_ci.p1), B, C ); 00145 00146 // return the maximum non-roundness 00147 priority = std::max( priority, (1.0-r) ); 00148 00149 } 00150 } 00151 else // binary mode 00152 { 00153 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it))); 00154 fhC = Base::mesh().face_handle( voh_it.handle() ); 00155 00156 for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it) 00157 { 00158 B = C; 00159 fhB = fhC; 00160 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it))); 00161 fhC = Base::mesh().face_handle( voh_it.handle() ); 00162 00163 if ( fhB == _ci.fl || fhB == _ci.fr ) 00164 continue; 00165 00166 priority = ( (r=roundness( vector_cast<Vec3f>(_ci.p1), B, C )) < min_r_) 00167 ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE; 00168 } 00169 } 00170 00171 return (float) priority; 00172 } 00173 00174 00175 00176 public: // specific methods 00177 00178 void set_min_angle( float _angle, bool /* _binary=true */ ) 00179 { 00180 assert( _angle > 0 && _angle < 60 ); 00181 00182 _angle = float(M_PI * _angle /180.0); 00183 00184 Vec3f A,B,C; 00185 00186 A = Vec3f( 0, 0, 0); 00187 B = Vec3f( 2*cos(_angle), 0, 0); 00188 C = Vec3f( cos(_angle), sin(_angle), 0); 00189 00190 double r1 = roundness(A,B,C); 00191 00192 _angle = float(0.5 * ( M_PI - _angle )); 00193 00194 A = Vec3f( 0, 0, 0); 00195 B = Vec3f( 2*cos(_angle), 0, 0); 00196 C = Vec3f( cos(_angle), sin(_angle), 0); 00197 00198 double r2 = roundness(A,B,C); 00199 00200 set_min_roundness( value_type(std::min(r1,r2)), true ); 00201 } 00202 00210 void set_min_roundness( value_type _min_roundness, bool _binary=true ) 00211 { 00212 assert( 0.0 <= _min_roundness && _min_roundness <= 1.0 ); 00213 min_r_ = _min_roundness; 00214 Base::set_binary(_binary); 00215 } 00216 00218 void unset_min_roundness() 00219 { 00220 min_r_ = -1.0; 00221 Base::set_binary(false); 00222 } 00223 00224 // Compute a normalized roundness of a triangle ABC 00225 // 00226 // Having 00227 // A,B,C corner points of triangle 00228 // a,b,c the vectors BC,CA,AB 00229 // Area area of triangle 00230 // 00231 // then define 00232 // 00233 // radius of circumference 00234 // R := ----------------------- 00235 // length of shortest edge 00236 // 00237 // ||a|| * ||b|| * ||c|| 00238 // --------------------- 00239 // 4 * Area ||a|| * ||b|| * ||c|| 00240 // = ----------------------- = ----------------------------------- 00241 // min( ||a||,||b||,||c||) 4 * Area * min( ||a||,||b||,||c|| ) 00242 // 00243 // ||a|| * ||b|| * ||c|| 00244 // = ------------------------------------------------------- 00245 // 4 * 1/2 * ||cross(B-A,C-A)|| * min( ||a||,||b||,||c|| ) 00246 // 00247 // a'a * b'b * c'c 00248 // R� = ---------------------------------------------------------- 00249 // 4 * cross(B-A,C-A)'cross(B-A,C-A) * min( a'a, b'b, c'c ) 00250 // 00251 // a'a * b'b * c'c 00252 // R = 1/2 * sqrt(---------------------------) 00253 // AA * min( a'a, b'b, c'c ) 00254 // 00255 // At angle 60� R has it's minimum for all edge lengths = sqrt(1/3) 00256 // 00257 // Define normalized roundness 00258 // 00259 // nR := sqrt(1/3) / R 00260 // 00261 // AA * min( a'a, b'b, c'c ) 00262 // = sqrt(4/3) * sqrt(---------------------------) 00263 // a'a * b'b * c'c 00264 // 00265 double roundness( const Vec3f& A, const Vec3f& B, const Vec3f &C ) 00266 { 00267 const value_type epsilon = value_type(1e-15); 00268 00269 static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60�,a=b=c, **) 00270 00271 Vec3f vecAC = C-A; 00272 Vec3f vecAB = B-A; 00273 00274 // compute squared values to avoid sqrt-computations 00275 value_type aa = (B-C).sqrnorm(); 00276 value_type bb = vecAC.sqrnorm(); 00277 value_type cc = vecAB.sqrnorm(); 00278 value_type AA = cross(vecAC,vecAB).sqrnorm(); // without factor 1/4 **) 00279 00280 if ( AA < epsilon ) 00281 return 0.0; 00282 00283 double nom = AA * std::min( std::min(aa,bb),cc ); 00284 double denom = aa * bb * cc; 00285 double nR = sqrt43 * sqrt(nom/denom); 00286 00287 return nR; 00288 } 00289 00290 private: 00291 00292 value_type min_r_; 00293 }; 00294 00295 00296 //============================================================================= 00297 } // END_NS_DECIMATER 00298 } // END_NS_OPENMESH 00299 //============================================================================= 00300 #if defined(OM_CC_MSVC) && defined(OM_ENABLE_WARNINGS) 00301 # pragma warning(default : OM_ENABLE_WARNINGS) 00302 # undef OM_ENABLE_WARNINGS 00303 #endif 00304 //============================================================================= 00305 #endif // OPENMESH_DECIMATER_MODROUNDNESST_HH defined 00306 //============================================================================= 00307