OpenMesh

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ModRoundnessT.hh
Go to the documentation of this file.
1 /*===========================================================================*\
2 * *
3 * OpenMesh *
4 * Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
5 * www.openmesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenMesh. *
9 * *
10 * OpenMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34
35 /*===========================================================================*\
36 * *
37 * $Revision: 737 $ *
38 * $Date: 2012-10-08 09:33:20 +0200 (Mo, 08. Okt 2012) $ *
39 * *
40 \*===========================================================================*/
41
46 //=============================================================================
47 //
48 // CLASS ModRoundnessT
49 //
50 //=============================================================================
51
52 #ifndef OPENMESH_DECIMATER_MODROUNDNESST_HH
53 #define OPENMESH_DECIMATER_MODROUNDNESST_HH
54
55
56 //== INCLUDES =================================================================
57
58 #include <OpenMesh/Tools/Decimater/ModBaseT.hh>
59 #include <math.h>
60
61 #if defined(OM_CC_MSVC)
62 # define OM_ENABLE_WARNINGS 4244
63 # pragma warning(disable : OM_ENABLE_WARNINGS )
64 #endif
65
66 //== NAMESPACE ================================================================
67
68 namespace OpenMesh { // BEGIN_NS_OPENMESH
69 namespace Decimater { // BEGIN_NS_DECIMATER
70
71
72 //== CLASS DEFINITION =========================================================
73
74
83 template <class MeshT>
84 class ModRoundnessT : public ModBaseT<MeshT>
85 {
86 public:
87 DECIMATING_MODULE( ModRoundnessT, MeshT, Roundness );
88
89 public:
90
91 // typedefs
92 typedef typename Mesh::Point Point;
93 typedef typename vector_traits<Point>::value_type value_type;
94
95 public:
96
98 ModRoundnessT( MeshT &_dec ) :
99 Base(_dec, false),
100 min_r_(-1.0)
101 { }
102
104 ~ModRoundnessT() { }
105
106 public: // inherited
107
118 float collapse_priority(const CollapseInfo& _ci)
119 {
120 // using namespace OpenMesh;
121
122 typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
123 double r;
124 double priority = 0.0; //==LEGAL_COLLAPSE
125 typename Mesh::FaceHandle fhC, fhB;
126 Vec3f B,C;
127
128 if ( min_r_ < 0.0 ) // continues mode
129 {
130 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
131 fhC = Base::mesh().face_handle( voh_it.handle() );
132
133 for (++voh_it; voh_it; ++voh_it)
134 {
135 B = C;
136 fhB = fhC;
137 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
138 fhC = Base::mesh().face_handle( voh_it.handle() );
139
140 if ( fhB == _ci.fl || fhB == _ci.fr )
141 continue;
142
143 // simulate collapse using position of v1
144 r = roundness( vector_cast<Vec3f>(_ci.p1), B, C );
145
146 // return the maximum non-roundness
147 priority = std::max( priority, (1.0-r) );
148
149 }
150 }
151 else // binary mode
152 {
153 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
154 fhC = Base::mesh().face_handle( voh_it.handle() );
155
156 for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
157 {
158 B = C;
159 fhB = fhC;
160 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
161 fhC = Base::mesh().face_handle( voh_it.handle() );
162
163 if ( fhB == _ci.fl || fhB == _ci.fr )
164 continue;
165
166 priority = ( (r=roundness( vector_cast<Vec3f>(_ci.p1), B, C )) < min_r_)
167 ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE;
168 }
169 }
170
171 return (float) priority;
172 }
173
175 void set_error_tolerance_factor(double _factor) {
176 if (this->is_binary()) {
177 if (_factor >= 0.0 && _factor <= 1.0) {
178 // the smaller the factor, the smaller min_r_ gets
179 // thus creating a stricter constraint
180 // division by error_tolerance_factor_ is for normalization
181 value_type min_roundness = min_r_ * _factor / this->error_tolerance_factor_;
182 set_min_roundness(min_roundness);
183 this->error_tolerance_factor_ = _factor;
184 }
185 }
186 }
187
188
189 public: // specific methods
190
191 void set_min_angle( float _angle, bool /* _binary=true */ )
192 {
193 assert( _angle > 0 && _angle < 60 );
194
195 _angle = float(M_PI * _angle /180.0);
196
197 Vec3f A,B,C;
198
199 A = Vec3f( 0, 0, 0);
200 B = Vec3f( 2*cos(_angle), 0, 0);
201 C = Vec3f( cos(_angle), sin(_angle), 0);
202
203 double r1 = roundness(A,B,C);
204
205 _angle = float(0.5 * ( M_PI - _angle ));
206
207 A = Vec3f( 0, 0, 0);
208 B = Vec3f( 2*cos(_angle), 0, 0);
209 C = Vec3f( cos(_angle), sin(_angle), 0);
210
211 double r2 = roundness(A,B,C);
212
213 set_min_roundness( value_type(std::min(r1,r2)), true );
214 }
215
223 void set_min_roundness( value_type _min_roundness, bool _binary=true )
224 {
225 assert( 0.0 <= _min_roundness && _min_roundness <= 1.0 );
226 min_r_ = _min_roundness;
227 Base::set_binary(_binary);
228 }
229
231 void unset_min_roundness()
232 {
233 min_r_ = -1.0;
234 Base::set_binary(false);
235 }
236
237 // Compute a normalized roundness of a triangle ABC
238 //
239 // Having
240 // A,B,C corner points of triangle
241 // a,b,c the vectors BC,CA,AB
242 // Area area of triangle
243 //
244 // then define
245 //
246 // radius of circumference
247 // R := -----------------------
248 // length of shortest edge
249 //
250 // ||a|| * ||b|| * ||c||
251 // ---------------------
252 // 4 * Area ||a|| * ||b|| * ||c||
253 // = ----------------------- = -----------------------------------
254 // min( ||a||,||b||,||c||) 4 * Area * min( ||a||,||b||,||c|| )
255 //
256 // ||a|| * ||b|| * ||c||
257 // = -------------------------------------------------------
258 // 4 * 1/2 * ||cross(B-A,C-A)|| * min( ||a||,||b||,||c|| )
259 //
260 // a'a * b'b * c'c
261 // R� = ----------------------------------------------------------
262 // 4 * cross(B-A,C-A)'cross(B-A,C-A) * min( a'a, b'b, c'c )
263 //
264 // a'a * b'b * c'c
265 // R = 1/2 * sqrt(---------------------------)
266 // AA * min( a'a, b'b, c'c )
267 //
268 // At angle 60� R has it's minimum for all edge lengths = sqrt(1/3)
269 //
270 // Define normalized roundness
271 //
272 // nR := sqrt(1/3) / R
273 //
274 // AA * min( a'a, b'b, c'c )
275 // = sqrt(4/3) * sqrt(---------------------------)
276 // a'a * b'b * c'c
277 //
278 double roundness( const Vec3f& A, const Vec3f& B, const Vec3f &C )
279 {
280 const value_type epsilon = value_type(1e-15);
281
282 static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60�,a=b=c, **)
283
284 Vec3f vecAC = C-A;
285 Vec3f vecAB = B-A;
286
287 // compute squared values to avoid sqrt-computations
288 value_type aa = (B-C).sqrnorm();
289 value_type bb = vecAC.sqrnorm();
290 value_type cc = vecAB.sqrnorm();
291 value_type AA = cross(vecAC,vecAB).sqrnorm(); // without factor 1/4 **)
292
293 if ( AA < epsilon )
294 return 0.0;
295
296 double nom = AA * std::min( std::min(aa,bb),cc );
297 double denom = aa * bb * cc;
298 double nR = sqrt43 * sqrt(nom/denom);
299
300 return nR;
301 }
302
303 private:
304
305 value_type min_r_;
306 };
307
308
309 //=============================================================================
310 } // END_NS_DECIMATER
311 } // END_NS_OPENMESH
312 //=============================================================================
313 #if defined(OM_CC_MSVC) && defined(OM_ENABLE_WARNINGS)
314 # pragma warning(default : OM_ENABLE_WARNINGS)
315 # undef OM_ENABLE_WARNINGS
316 #endif
317 //=============================================================================
318 #endif // OPENMESH_DECIMATER_MODROUNDNESST_HH defined
319 //=============================================================================
320