Developer Documentation

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

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
SmootherT.cc
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 * *
44 * $Revision$ *
45 * $Date$ *
46 * *
47 \*===========================================================================*/
48
53 //=============================================================================
54 //
55 // CLASS SmootherT - IMPLEMENTATION
56 //
57 //=============================================================================
58
59 #define OPENMESH_SMOOTHERT_C
60
61 //== INCLUDES =================================================================
62
63 #include <OpenMesh/Core/Utils/vector_cast.hh>
64 #include <OpenMesh/Tools/Smoother/SmootherT.hh>
65
66 //== NAMESPACES ===============================================================
67
68
69 namespace OpenMesh {
70 namespace Smoother {
71
72
73 //== IMPLEMENTATION ==========================================================
74
75
76 template <class Mesh>
77 SmootherT<Mesh>::
78 SmootherT(Mesh& _mesh)
79 : mesh_(_mesh),
80 skip_features_(false)
81 {
82 // request properties
83 mesh_.request_vertex_status();
84 mesh_.request_face_normals();
85 mesh_.request_vertex_normals();
86
87 // custom properties
88 mesh_.add_property(original_positions_);
89 mesh_.add_property(original_normals_);
90 mesh_.add_property(new_positions_);
91 mesh_.add_property(is_active_);
92
93
94 // default settings
95 component_ = Tangential_and_Normal;
96 continuity_ = C0;
97 tolerance_ = -1.0;
98 }
99
100
101 //-----------------------------------------------------------------------------
102
103
104 template <class Mesh>
105 SmootherT<Mesh>::
106 ~SmootherT()
107 {
108 // free properties
109 mesh_.release_vertex_status();
110 mesh_.release_face_normals();
111 mesh_.release_vertex_normals();
112
113 // free custom properties
114 mesh_.remove_property(original_positions_);
115 mesh_.remove_property(original_normals_);
116 mesh_.remove_property(new_positions_);
117 mesh_.remove_property(is_active_);
118 }
119
120
121 //-----------------------------------------------------------------------------
122
123
124 template <class Mesh>
125 void
126 SmootherT<Mesh>::
127 initialize(Component _comp, Continuity _cont)
128 {
129 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
130
131
132 // store smoothing settings
133 component_ = _comp;
134 continuity_ = _cont;
135
136
137 // update normals
138 mesh_.update_face_normals();
139 mesh_.update_vertex_normals();
140
141
142 // store original points & normals
143 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
144 {
145 mesh_.property(original_positions_, *v_it) = mesh_.point(*v_it);
146 mesh_.property(original_normals_, *v_it) = mesh_.normal(*v_it);
147 }
148 }
149
150
151 //-----------------------------------------------------------------------------
152
153
154 template <class Mesh>
155 void
156 SmootherT<Mesh>::
157 set_active_vertices()
158 {
159 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
160
161
162 // is something selected?
163 bool nothing_selected(true);
164 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
165 if (mesh_.status(*v_it).selected())
166 { nothing_selected = false; break; }
167
168
169 // tagg all active vertices
170 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
171 {
172 bool active = ((nothing_selected || mesh_.status(*v_it).selected())
173 && !mesh_.is_boundary(*v_it)
174 && !mesh_.status(*v_it).locked());
175
176 if ( skip_features_ ) {
177
178 active = active && !mesh_.status(*v_it).feature();
179
180 typename Mesh::VertexOHalfedgeIter voh_it(mesh_,*v_it);
181 for ( ; voh_it.is_valid() ; ++voh_it ) {
182
183 // If the edge is a feature edge, skip the current vertex while smoothing
184 if ( mesh_.status(mesh_.edge_handle(*voh_it)).feature() )
185 active = false;
186
187 typename Mesh::FaceHandle fh1 = mesh_.face_handle(*voh_it );
188 typename Mesh::FaceHandle fh2 = mesh_.face_handle(mesh_.opposite_halfedge_handle(*voh_it ) );
189
190 // If one of the faces is a feature, lock current vertex
191 if ( fh1.is_valid() && mesh_.status( fh1 ).feature() )
192 active = false;
193 if ( fh2.is_valid() && mesh_.status( fh2 ).feature() )
194 active = false;
195
196 }
197 }
198
199 mesh_.property(is_active_, *v_it) = active;
200 }
201
202
203 // C1: remove one ring of boundary vertices
204 if (continuity_ == C1)
205 {
206 typename Mesh::VVIter vv_it;
207
208 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
209 if (mesh_.is_boundary(*v_it))
210 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
211 mesh_.property(is_active_, *vv_it) = false;
212 }
213
214
215 // C2: remove two rings of boundary vertices
216 if (continuity_ == C2)
217 {
218 typename Mesh::VVIter vv_it;
219
220 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
221 {
222 mesh_.status(*v_it).set_tagged(false);
223 mesh_.status(*v_it).set_tagged2(false);
224 }
225
226 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
227 if (mesh_.is_boundary(*v_it))
228 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
229 mesh_.status(*v_it).set_tagged(true);
230
231 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
232 if (mesh_.status(*v_it).tagged())
233 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
234 mesh_.status(*v_it).set_tagged2(true);
235
236 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
237 {
238 if (mesh_.status(*v_it).tagged2())
239 mesh_.property(is_active_, *vv_it) = false;
240 mesh_.status(*v_it).set_tagged(false);
241 mesh_.status(*v_it).set_tagged2(false);
242 }
243 }
244 }
245
246
247 //-----------------------------------------------------------------------------
248
249
250 template <class Mesh>
251 void
252 SmootherT<Mesh>::
253 set_relative_local_error(Scalar _err)
254 {
255 if (!mesh_.vertices_empty())
256 {
257 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
258 v_end(mesh_.vertices_end());
259
260
261 // compute bounding box
262 Point bb_min, bb_max;
263 bb_min = bb_max = mesh_.point(*v_it);
264 for (++v_it; v_it!=v_end; ++v_it)
265 {
266 bb_min.minimize(mesh_.point(*v_it));
267 bb_max.maximize(mesh_.point(*v_it));
268 }
269
270
271 // abs. error = rel. error * bounding-diagonal
272 set_absolute_local_error(_err * (bb_max-bb_min).norm());
273 }
274 }
275
276
277 //-----------------------------------------------------------------------------
278
279
280 template <class Mesh>
281 void
282 SmootherT<Mesh>::
283 set_absolute_local_error(Scalar _err)
284 {
285 tolerance_ = _err;
286 }
287
288
289 //-----------------------------------------------------------------------------
290
291
292 template <class Mesh>
293 void
294 SmootherT<Mesh>::
295 disable_local_error_check()
296 {
297 tolerance_ = -1.0;
298 }
299
300
301 //-----------------------------------------------------------------------------
302
303
304 template <class Mesh>
305 void
306 SmootherT<Mesh>::
307 smooth(unsigned int _n)
308 {
309 // mark active vertices
310 set_active_vertices();
311
312 // smooth _n iterations
313 while (_n--)
314 {
315 compute_new_positions();
316
317 if (component_ == Tangential)
318 project_to_tangent_plane();
319
320 else if (tolerance_ >= 0.0)
321 local_error_check();
322
323 move_points();
324 }
325 }
326
327
328 //-----------------------------------------------------------------------------
329
330
331 template <class Mesh>
332 void
333 SmootherT<Mesh>::
334 compute_new_positions()
335 {
336 switch (continuity_)
337 {
338 case C0:
339 compute_new_positions_C0();
340 break;
341
342 case C1:
343 compute_new_positions_C1();
344 break;
345
346 case C2:
347 break;
348 }
349 }
350
351
352 //-----------------------------------------------------------------------------
353
354
355 template <class Mesh>
356 void
357 SmootherT<Mesh>::
358 project_to_tangent_plane()
359 {
360 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
361 v_end(mesh_.vertices_end());
362 // Normal should be a vector type. In some environment a vector type
363 // is different from point type, e.g. OpenSG!
364 typename Mesh::Normal translation, normal;
365
366
367 for (; v_it != v_end; ++v_it)
368 {
369 if (is_active(*v_it))
370 {
371 translation = new_position(*v_it)-orig_position(*v_it);
372 normal = orig_normal(*v_it);
373 normal *= dot(translation, normal);
374 translation -= normal;
375 translation += vector_cast<typename Mesh::Normal>(orig_position(*v_it));
376 set_new_position(*v_it, translation);
377 }
378 }
379 }
380
381
382 //-----------------------------------------------------------------------------
383
384
385 template <class Mesh>
386 void
387 SmootherT<Mesh>::
388 local_error_check()
389 {
390 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
391 v_end(mesh_.vertices_end());
392
393 typename Mesh::Normal translation;
394 typename Mesh::Scalar s;
395
396
397 for (; v_it != v_end; ++v_it)
398 {
399 if (is_active(*v_it))
400 {
401 translation = new_position(*v_it) - orig_position(*v_it);
402
403 s = fabs(dot(translation, orig_normal(*v_it)));
404
405 if (s > tolerance_)
406 {
407 translation *= (tolerance_ / s);
408 translation += vector_cast<NormalType>(orig_position(*v_it));
409 set_new_position(*v_it, translation);
410 }
411 }
412 }
413 }
414
415
416 //-----------------------------------------------------------------------------
417
418
419 template <class Mesh>
420 void
421 SmootherT<Mesh>::
422 move_points()
423 {
424 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
425 v_end(mesh_.vertices_end());
426
427 for (; v_it != v_end; ++v_it)
428 if (is_active(*v_it))
429 mesh_.set_point(*v_it, mesh_.property(new_positions_, *v_it));
430 }
431
432
433 //=============================================================================
434 } // namespace Smoother
435 } // namespace OpenMesh
436 //=============================================================================
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::Smoother::SmootherT::initialize
void initialize(Component _comp, Continuity _cont)
Definition: SmootherT.cc:127
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:86
OpenMesh::TriMesh_ArrayKernelT< CustomTraits >
OpenMesh::Smoother::SmootherT::disable_local_error_check
void disable_local_error_check()
Disable error control of the smoother.
Definition: SmootherT.cc:295
OpenMesh::Smoother::SmootherT::set_active_vertices
void set_active_vertices()
Find active vertices. Resets tagged status !
Definition: SmootherT.cc:157
OpenMesh::Smoother::SmootherT::Component
Component
Definition: SmootherT.hh:92
OpenMesh::Smoother::SmootherT::set_absolute_local_error
void set_absolute_local_error(Scalar _err)
Set local error as an absolute value.
Definition: SmootherT.cc:283
OpenMesh::Smoother::SmootherT::smooth
virtual void smooth(unsigned int _n)
Do _n smoothing iterations.
Definition: SmootherT.cc:307
OpenMesh::PolyMeshT::update_vertex_normals
void update_vertex_normals()
Update normal vectors for all vertices.
Definition: PolyMeshT.cc:448
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
OpenMesh::PolyMeshT::VertexOHalfedgeIter
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:166
OpenMesh::Smoother::SmootherT::SmootherT
SmootherT(Mesh &_mesh)
constructor & destructor
Definition: SmootherT.cc:78
OpenMesh::Smoother::SmootherT::Tangential_and_Normal
Smooth tangential and normal direction.
Definition: SmootherT.hh:95
OpenMesh::dot
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
Definition: VectorAdapter.hh:181
OpenMesh::PolyMeshT::Scalar
Kernel::Scalar Scalar
Scalar type.
Definition: PolyMeshT.hh:113
OpenMesh::Smoother::SmootherT
Definition: SmootherT.hh:81
SmootherT.hh
OpenMesh::Smoother::SmootherT::set_relative_local_error
void set_relative_local_error(Scalar _err)
Set local error relative to bounding box.
Definition: SmootherT.cc:253
OpenMesh::PolyMeshT::Normal
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:117