| OpenMesh

ModRoundnessT.hh
Go to the documentation of this file.
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42
43
48 //=============================================================================
49 //
50 // CLASS ModRoundnessT
51 //
52 //=============================================================================
53
54 #ifndef OPENMESH_DECIMATER_MODROUNDNESST_HH
55 #define OPENMESH_DECIMATER_MODROUNDNESST_HH
56
57
58 //== INCLUDES =================================================================
59
60 #include <OpenMesh/Tools/Decimater/ModBaseT.hh>
61 #include <math.h>
62
63 #if defined(OM_CC_MSVC)
64 # define OM_ENABLE_WARNINGS 4244
65 # pragma warning(disable : OM_ENABLE_WARNINGS )
66 #endif
67
68 //== NAMESPACE ================================================================
69
70 namespace OpenMesh { // BEGIN_NS_OPENMESH
71 namespace Decimater { // BEGIN_NS_DECIMATER
72
73
74 //== CLASS DEFINITION =========================================================
75
76
85 template <class MeshT>
86 class ModRoundnessT : public ModBaseT<MeshT>
87 {
88 public:
89 DECIMATING_MODULE( ModRoundnessT, MeshT, Roundness );
90
91 public:
92
93 // typedefs
94 typedef typename MeshT::Point Point;
95 typedef typename vector_traits<Point>::value_type value_type;
96
97 public:
98
100 explicit ModRoundnessT( MeshT &_dec ) :
101 Base(_dec, false),
102 min_r_(-1.0)
103 { }
104
106 ~ModRoundnessT() { }
107
108 public: // inherited
109
120 float collapse_priority(const CollapseInfo& _ci) override
121 {
122 // using namespace OpenMesh;
123
124 typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
125 double r;
126 double priority = 0.0; //==LEGAL_COLLAPSE
127 typename Mesh::FaceHandle fhC, fhB;
128 Vec3f B,C;
129
130 if ( min_r_ < 0.0f ) // continues mode
131 {
132 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(*voh_it)));
133 fhC = Base::mesh().face_handle( *voh_it );
134
135 for (++voh_it; voh_it.is_valid(); ++voh_it)
136 {
137 B = C;
138 fhB = fhC;
139 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(*voh_it)));
140 fhC = Base::mesh().face_handle( *voh_it );
141
142 if ( fhB == _ci.fl || fhB == _ci.fr )
143 continue;
144
145 // simulate collapse using position of v1
146 r = roundness( vector_cast<Vec3f>(_ci.p1), B, C );
147
148 // return the maximum non-roundness
149 priority = std::max( priority, (1.0-r) );
150
151 }
152 }
153 else // binary mode
154 {
155 C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(*voh_it)));
156 fhC = Base::mesh().face_handle( *voh_it );
157
158 for (++voh_it; voh_it.is_valid() && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
159 {
160 B = C;
161 fhB = fhC;
162 C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(*voh_it)));
163 fhC = Base::mesh().face_handle( *voh_it );
164
165 if ( fhB == _ci.fl || fhB == _ci.fr )
166 continue;
167
168 priority = ( (r=roundness( vector_cast<Vec3f>(_ci.p1), B, C )) < min_r_)
169 ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE;
170 }
171 }
172
173 return (float) priority;
174 }
175
177 void set_error_tolerance_factor(double _factor) override {
178 if (this->is_binary()) {
179 if (_factor >= 0.0 && _factor <= 1.0) {
180 // the smaller the factor, the smaller min_r_ gets
181 // thus creating a stricter constraint
182 // division by error_tolerance_factor_ is for normalization
183 value_type min_roundness = min_r_ * static_cast<value_type>(_factor / this->error_tolerance_factor_);
184 set_min_roundness(min_roundness);
185 this->error_tolerance_factor_ = _factor;
186 }
187 }
188 }
189
190
191 public: // specific methods
192
193 void set_min_angle( float _angle, bool /* _binary=true */ )
194 {
195 assert( _angle > 0 && _angle < 60 );
196
197 _angle = float(M_PI * _angle /180.0);
198
199 Vec3f A,B,C;
200
201 A = Vec3f( 0.0f, 0.0f, 0.0f);
202 B = Vec3f( 2.0f * cos(_angle), 0.0f, 0.0f);
203 C = Vec3f( cos(_angle), sin(_angle), 0.0f);
204
205 double r1 = roundness(A,B,C);
206
207 _angle = float(0.5 * ( M_PI - _angle ));
208
209 A = Vec3f( 0.0f, 0.0f, 0.0f);
210 B = Vec3f( 2.0f*cos(_angle), 0.0f, 0.0f);
211 C = Vec3f( cos(_angle), sin(_angle), 0.0f);
212
213 double r2 = roundness(A,B,C);
214
215 set_min_roundness( value_type(std::min(r1,r2)), true );
216 }
217
225 void set_min_roundness( value_type _min_roundness, bool _binary=true )
226 {
227 assert( 0.0 <= _min_roundness && _min_roundness <= 1.0 );
228 min_r_ = _min_roundness;
229 Base::set_binary(_binary);
230 }
231
233 void unset_min_roundness()
234 {
235 min_r_ = -1.0;
236 Base::set_binary(false);
237 }
238
239 // Compute a normalized roundness of a triangle ABC
240 //
241 // Having
242 // A,B,C corner points of triangle
243 // a,b,c the vectors BC,CA,AB
244 // Area area of triangle
245 //
246 // then define
247 //
248 // radius of circumference
249 // R := -----------------------
250 // length of shortest edge
251 //
252 // ||a|| * ||b|| * ||c||
253 // ---------------------
254 // 4 * Area ||a|| * ||b|| * ||c||
255 // = ----------------------- = -----------------------------------
256 // min( ||a||,||b||,||c||) 4 * Area * min( ||a||,||b||,||c|| )
257 //
258 // ||a|| * ||b|| * ||c||
259 // = -------------------------------------------------------
260 // 4 * 1/2 * ||cross(B-A,C-A)|| * min( ||a||,||b||,||c|| )
261 //
262 // a'a * b'b * c'c
263 // R� = ----------------------------------------------------------
264 // 4 * cross(B-A,C-A)'cross(B-A,C-A) * min( a'a, b'b, c'c )
265 //
266 // a'a * b'b * c'c
267 // R = 1/2 * sqrt(---------------------------)
268 // AA * min( a'a, b'b, c'c )
269 //
270 // At angle 60� R has it's minimum for all edge lengths = sqrt(1/3)
271 //
272 // Define normalized roundness
273 //
274 // nR := sqrt(1/3) / R
275 //
276 // AA * min( a'a, b'b, c'c )
277 // = sqrt(4/3) * sqrt(---------------------------)
278 // a'a * b'b * c'c
279 //
280 double roundness( const Vec3f& A, const Vec3f& B, const Vec3f &C )
281 {
282 const value_type epsilon = value_type(1e-15);
283
284 static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60�,a=b=c, **)
285
286 Vec3f vecAC = C-A;
287 Vec3f vecAB = B-A;
288
289 // compute squared values to avoid sqrt-computations
290 value_type aa = (B-C).sqrnorm();
291 value_type bb = vecAC.sqrnorm();
292 value_type cc = vecAB.sqrnorm();
293 value_type AA = cross(vecAC,vecAB).sqrnorm(); // without factor 1/4 **)
294
295 if ( AA < epsilon )
296 return 0.0;
297
298 double nom = AA * std::min( std::min(aa,bb),cc );
299 double denom = aa * bb * cc;
300 double nR = sqrt43 * sqrt(nom/denom);
301
302 return nR;
303 }
304
305 private:
306
307 value_type min_r_;
308 };
309
310
311 //=============================================================================
312 } // END_NS_DECIMATER
313 } // END_NS_OPENMESH
314 //=============================================================================
315 #if defined(OM_CC_MSVC) && defined(OM_ENABLE_WARNINGS)
316 # pragma warning(default : OM_ENABLE_WARNINGS)
317 # undef OM_ENABLE_WARNINGS
318 #endif
319 //=============================================================================
320 #endif // OPENMESH_DECIMATER_MODROUNDNESST_HH defined
321 //=============================================================================
322
OpenMesh::vector_cast
void vector_cast(const src_t &_src, dst_t &_dst, GenProg::Int2Type< n >)
Cast vector type to another vector type by copying the vector elements.
Definition: vector_cast.hh:81
OpenMesh::Decimater::ModBaseT::is_binary
bool is_binary(void) const
Returns true if criteria returns a binary value.
Definition: ModBaseT.hh:220
OpenMesh::Decimater::CollapseInfoT::fl
Mesh::FaceHandle fl
Left face.
Definition: CollapseInfoT.hh:95
OpenMesh::Decimater::ModRoundnessT
Use Roundness of triangles to control decimation.
Definition: ModRoundnessT.hh:86
OpenMesh::Decimater::ModRoundnessT::unset_min_roundness
void unset_min_roundness()
Unset minimum value constraint and enable non-binary mode.
Definition: ModRoundnessT.hh:233
OpenMesh::VectorT::sqrnorm
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:421
OpenMesh::VectorT< float, 3 >
OpenMesh::Decimater::ModRoundnessT::set_min_roundness
void set_min_roundness(value_type _min_roundness, bool _binary=true)
Set a minimum roundness value.
Definition: ModRoundnessT.hh:225
ModBaseT.hh
Base class for all decimation modules.
OpenMesh::vector_traits
Helper class providing information about a vector type.
Definition: vector_traits.hh:88
OpenMesh::PolyMeshT::ConstVertexOHalfedgeIter
Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:173
OpenMesh::Vec3f
VectorT< float, 3 > Vec3f
3-float vector
Definition: Vector11T.hh:850
OpenMesh::Decimater::ModRoundnessT::set_error_tolerance_factor
void set_error_tolerance_factor(double _factor) override
set the percentage of minimum roundness
Definition: ModRoundnessT.hh:177
DECIMATING_MODULE
#define DECIMATING_MODULE(Classname, MeshT, Name)
Convenience macro, to be used in derived modules The macro defines the types.
Definition: ModBaseT.hh:149
OpenMesh::Decimater::ModBaseT
Base class for all decimation modules.
Definition: ModBaseT.hh:192
OpenMesh::Decimater::CollapseInfoT::fr
Mesh::FaceHandle fr
Right face.
Definition: CollapseInfoT.hh:96
OpenMesh::Decimater::ModRoundnessT::ModRoundnessT
ModRoundnessT(MeshT &_dec)
Constructor.
Definition: ModRoundnessT.hh:100
OpenMesh::Decimater::ModRoundnessT::~ModRoundnessT
~ModRoundnessT()
Destructor.
Definition: ModRoundnessT.hh:106
OpenMesh::Decimater::CollapseInfoT::p1
Mesh::Point p1
Positions of remaining vertex.
Definition: CollapseInfoT.hh:94
OpenMesh::cross
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
Definition: VectorAdapter.hh:191
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::Decimater::CollapseInfoT
Stores information about a halfedge collapse.
Definition: CollapseInfoT.hh:74
OpenMesh::Decimater::CollapseInfoT::v0
Mesh::VertexHandle v0
Vertex to be removed.
Definition: CollapseInfoT.hh:91
OpenMesh::Decimater::ModRoundnessT::collapse_priority
float collapse_priority(const CollapseInfo &_ci) override
Compute collapse priority due to roundness of triangle.
Definition: ModRoundnessT.hh:120