00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00046
00047
00048
00049
00050
00051
00052 #define OPENMESH_SMOOTHERT_C
00053
00054
00055
00056 #include <OpenMesh/Core/Utils/vector_cast.hh>
00057 #include <OpenMesh/Tools/Smoother/SmootherT.hh>
00058
00059
00060
00061
00062 namespace OpenMesh {
00063 namespace Smoother {
00064
00065
00066
00067
00068
00069 template <class Mesh>
00070 SmootherT<Mesh>::
00071 SmootherT(Mesh& _mesh)
00072 : mesh_(_mesh),
00073 skip_features_(false)
00074 {
00075
00076 mesh_.request_vertex_status();
00077 mesh_.request_face_normals();
00078 mesh_.request_vertex_normals();
00079
00080
00081 mesh_.add_property(original_positions_);
00082 mesh_.add_property(original_normals_);
00083 mesh_.add_property(new_positions_);
00084 mesh_.add_property(is_active_);
00085
00086
00087
00088 component_ = Tangential_and_Normal;
00089 continuity_ = C0;
00090 tolerance_ = -1.0;
00091 }
00092
00093
00094
00095
00096
00097 template <class Mesh>
00098 SmootherT<Mesh>::
00099 ~SmootherT()
00100 {
00101
00102 mesh_.release_vertex_status();
00103 mesh_.release_face_normals();
00104 mesh_.release_vertex_normals();
00105
00106
00107 mesh_.remove_property(original_positions_);
00108 mesh_.remove_property(original_normals_);
00109 mesh_.remove_property(new_positions_);
00110 mesh_.remove_property(is_active_);
00111 }
00112
00113
00114
00115
00116
00117 template <class Mesh>
00118 void
00119 SmootherT<Mesh>::
00120 initialize(Component _comp, Continuity _cont)
00121 {
00122 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
00123
00124
00125
00126 component_ = _comp;
00127 continuity_ = _cont;
00128
00129
00130
00131 mesh_.update_face_normals();
00132 mesh_.update_vertex_normals();
00133
00134
00135
00136 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00137 {
00138 mesh_.property(original_positions_, v_it) = mesh_.point(v_it);
00139 mesh_.property(original_normals_, v_it) = mesh_.normal(v_it);
00140 }
00141 }
00142
00143
00144
00145
00146
00147 template <class Mesh>
00148 void
00149 SmootherT<Mesh>::
00150 set_active_vertices()
00151 {
00152 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
00153
00154
00155
00156 bool nothing_selected(true);
00157 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00158 if (mesh_.status(v_it).selected())
00159 { nothing_selected = false; break; }
00160
00161
00162
00163 bool active;
00164 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00165 {
00166 active = ((nothing_selected || mesh_.status(v_it).selected())
00167 && !mesh_.is_boundary(v_it)
00168 && !mesh_.status(v_it).locked());
00169
00170 if ( skip_features_ ) {
00171
00172 active = active && !mesh_.status(v_it).feature();
00173
00174 typename Mesh::VertexOHalfedgeIter voh_it(mesh_,v_it);
00175 for ( ; voh_it ; ++voh_it ) {
00176
00177
00178 if ( mesh_.status(mesh_.edge_handle(voh_it.handle())).feature() )
00179 active = false;
00180
00181 typename Mesh::FaceHandle fh1 = mesh_.face_handle(voh_it.handle() );
00182 typename Mesh::FaceHandle fh2 = mesh_.face_handle(mesh_.opposite_halfedge_handle(voh_it.handle() ) );
00183
00184
00185 if ( fh1.is_valid() && mesh_.status( fh1 ).feature() )
00186 active = false;
00187 if ( fh2.is_valid() && mesh_.status( fh2 ).feature() )
00188 active = false;
00189
00190 }
00191 }
00192
00193 mesh_.property(is_active_, v_it) = active;
00194 }
00195
00196
00197
00198 if (continuity_ == C1)
00199 {
00200 typename Mesh::VVIter vv_it;
00201
00202 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00203 if (mesh_.is_boundary(v_it))
00204 for (vv_it=mesh_.vv_iter(v_it); vv_it; ++vv_it)
00205 mesh_.property(is_active_, vv_it) = false;
00206 }
00207
00208
00209
00210 if (continuity_ == C2)
00211 {
00212 typename Mesh::VVIter vv_it;
00213
00214 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00215 {
00216 mesh_.status(v_it).set_tagged(false);
00217 mesh_.status(v_it).set_tagged2(false);
00218 }
00219
00220 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00221 if (mesh_.is_boundary(v_it))
00222 for (vv_it=mesh_.vv_iter(v_it); vv_it; ++vv_it)
00223 mesh_.status(v_it).set_tagged(true);
00224
00225 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00226 if (mesh_.status(v_it).tagged())
00227 for (vv_it=mesh_.vv_iter(v_it); vv_it; ++vv_it)
00228 mesh_.status(v_it).set_tagged2(true);
00229
00230 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
00231 {
00232 if (mesh_.status(v_it).tagged2())
00233 mesh_.property(is_active_, vv_it) = false;
00234 mesh_.status(v_it).set_tagged(false);
00235 mesh_.status(v_it).set_tagged2(false);
00236 }
00237 }
00238 }
00239
00240
00241
00242
00243
00244 template <class Mesh>
00245 void
00246 SmootherT<Mesh>::
00247 set_relative_local_error(Scalar _err)
00248 {
00249 if (!mesh_.vertices_empty())
00250 {
00251 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
00252 v_end(mesh_.vertices_end());
00253
00254
00255
00256 Point bb_min, bb_max;
00257 bb_min = bb_max = mesh_.point(v_it);
00258 for (++v_it; v_it!=v_end; ++v_it)
00259 {
00260 bb_min.minimize(mesh_.point(v_it));
00261 bb_max.minimize(mesh_.point(v_it));
00262 }
00263
00264
00265
00266 set_absolute_error(_err * (bb_max-bb_min).norm());
00267 }
00268 }
00269
00270
00271
00272
00273
00274 template <class Mesh>
00275 void
00276 SmootherT<Mesh>::
00277 set_absolute_local_error(Scalar _err)
00278 {
00279 tolerance_ = _err;
00280 }
00281
00282
00283
00284
00285
00286 template <class Mesh>
00287 void
00288 SmootherT<Mesh>::
00289 disable_local_error_check()
00290 {
00291 tolerance_ = -1.0;
00292 }
00293
00294
00295
00296
00297
00298 template <class Mesh>
00299 void
00300 SmootherT<Mesh>::
00301 smooth(unsigned int _n)
00302 {
00303
00304 set_active_vertices();
00305
00306
00307 while (_n--)
00308 {
00309 compute_new_positions();
00310
00311 if (component_ == Tangential)
00312 project_to_tangent_plane();
00313
00314 else if (tolerance_ >= 0.0)
00315 local_error_check();
00316
00317 move_points();
00318 }
00319 }
00320
00321
00322
00323
00324
00325 template <class Mesh>
00326 void
00327 SmootherT<Mesh>::
00328 compute_new_positions()
00329 {
00330 switch (continuity_)
00331 {
00332 case C0:
00333 compute_new_positions_C0();
00334 break;
00335
00336 case C1:
00337 compute_new_positions_C1();
00338 break;
00339
00340 case C2:
00341 break;
00342 }
00343 }
00344
00345
00346
00347
00348
00349 template <class Mesh>
00350 void
00351 SmootherT<Mesh>::
00352 project_to_tangent_plane()
00353 {
00354 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
00355 v_end(mesh_.vertices_end());
00356
00357
00358 typename Mesh::Normal translation, normal;
00359
00360
00361 for (; v_it != v_end; ++v_it)
00362 {
00363 if (is_active(v_it))
00364 {
00365 translation = new_position(v_it)-orig_position(v_it);
00366 normal = orig_normal(v_it);
00367 normal *= dot(translation, normal);
00368 translation -= normal;
00369 translation += vector_cast<typename Mesh::Normal>(orig_position(v_it));
00370 set_new_position(v_it, translation);
00371 }
00372 }
00373 }
00374
00375
00376
00377
00378
00379 template <class Mesh>
00380 void
00381 SmootherT<Mesh>::
00382 local_error_check()
00383 {
00384 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
00385 v_end(mesh_.vertices_end());
00386
00387 typename Mesh::Normal translation;
00388 typename Mesh::Scalar s;
00389
00390
00391 for (; v_it != v_end; ++v_it)
00392 {
00393 if (is_active(v_it))
00394 {
00395 translation = new_position(v_it) - orig_position(v_it);
00396
00397 s = fabs(dot(translation, orig_normal(v_it)));
00398
00399 if (s > tolerance_)
00400 {
00401 translation *= (tolerance_ / s);
00402 translation += vector_cast<NormalType>(orig_position(v_it));
00403 set_new_position(v_it, translation);
00404 }
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413 template <class Mesh>
00414 void
00415 SmootherT<Mesh>::
00416 move_points()
00417 {
00418 typename Mesh::VertexIter v_it(mesh_.vertices_begin()),
00419 v_end(mesh_.vertices_end());
00420
00421 for (; v_it != v_end; ++v_it)
00422 if (is_active(v_it))
00423 mesh_.set_point(v_it, mesh_.property(new_positions_, v_it));
00424 }
00425
00426
00427
00428 }
00429 }
00430