OpenMesh
LaplaceSmootherT_impl.hh
Go to the documentation of this file.
1/* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2025, 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 LaplaceSmootherT - IMPLEMENTATION
51//
52//=============================================================================
53
54#define OPENMESH_LAPLACE_SMOOTHERT_C
55
56//== INCLUDES =================================================================
57
59
60
61//== NAMESPACES ===============================================================
62
63
64namespace OpenMesh {
65namespace Smoother {
66
67
68//== IMPLEMENTATION ==========================================================
69
70
71template <class Mesh>
72LaplaceSmootherT<Mesh>::
73LaplaceSmootherT(Mesh& _mesh)
74 : SmootherT<Mesh>(_mesh)
75{
76 // custom properties
77 Base::mesh_.add_property(vertex_weights_);
78 Base::mesh_.add_property(edge_weights_);
79}
80
81
82//-----------------------------------------------------------------------------
83
84
85template <class Mesh>
86LaplaceSmootherT<Mesh>::
87~LaplaceSmootherT()
88{
89 // free custom properties
90 Base::mesh_.remove_property(vertex_weights_);
91 Base::mesh_.remove_property(edge_weights_);
92}
93
94
95//-----------------------------------------------------------------------------
96
97
98template <class Mesh>
99void
100LaplaceSmootherT<Mesh>::
101initialize(Component _comp, Continuity _cont)
102{
103 SmootherT<Mesh>::initialize(_comp, _cont);
104
105 // calculate weights
106 switch (_comp)
107 {
108 case Base::Tangential:
109 compute_weights(UniformWeighting);
110 break;
111
112
113 case Base::Normal:
114 compute_weights(CotWeighting);
115 break;
116
117
118 case Base::Tangential_and_Normal:
119 compute_weights(UniformWeighting);
120 break;
121 }
122}
123
124
125//-----------------------------------------------------------------------------
126
127
128template <class Mesh>
129void
130LaplaceSmootherT<Mesh>::
131compute_weights(LaplaceWeighting _weighting)
132{
133 typename Mesh::VertexIter v_it, v_end(Base::mesh_.vertices_end());
134 typename Mesh::EdgeIter e_it, e_end(Base::mesh_.edges_end());
135 typename Mesh::HalfedgeHandle heh0, heh1, heh2;
136 typename Mesh::VertexHandle v0, v1;
137 typename Mesh::Normal d0, d1;
138 typename Mesh::Scalar weight, lb(-1.0), ub(1.0);
139
140
141
142 // init vertex weights
143 for (v_it=Base::mesh_.vertices_begin(); v_it!=v_end; ++v_it)
144 Base::mesh_.property(vertex_weights_, *v_it) = 0.0;
145
146
147
148 switch (_weighting)
149 {
150 // Uniform weighting
151 case UniformWeighting:
152 {
153 for (e_it=Base::mesh_.edges_begin(); e_it!=e_end; ++e_it)
154 {
155 heh0 = Base::mesh_.halfedge_handle(*e_it, 0);
156 heh1 = Base::mesh_.halfedge_handle(*e_it, 1);
157 v0 = Base::mesh_.to_vertex_handle(heh0);
158 v1 = Base::mesh_.to_vertex_handle(heh1);
159
160 Base::mesh_.property(edge_weights_, *e_it) = 1.0;
161 Base::mesh_.property(vertex_weights_, v0) += 1.0;
162 Base::mesh_.property(vertex_weights_, v1) += 1.0;
163 }
164
165 break;
166 }
167
168
169 // Cotangent weighting
170 case CotWeighting:
171 {
172 for (e_it=Base::mesh_.edges_begin(); e_it!=e_end; ++e_it)
173 {
174 const typename Mesh::Point *p0, *p1, *p2;
175
176 weight = 0.0;
177
178 heh0 = Base::mesh_.halfedge_handle(*e_it, 0);
179 v0 = Base::mesh_.to_vertex_handle(heh0);
180 p0 = &Base::mesh_.point(v0);
181
182 heh1 = Base::mesh_.halfedge_handle(*e_it, 1);
183 v1 = Base::mesh_.to_vertex_handle(heh1);
184 p1 = &Base::mesh_.point(v1);
185
186 heh2 = Base::mesh_.next_halfedge_handle(heh0);
187 p2 = &Base::mesh_.point(Base::mesh_.to_vertex_handle(heh2));
188 d0 = (*p0 - *p2); normalize(d0);
189 d1 = (*p1 - *p2); normalize(d1);
190 weight += static_cast<typename Mesh::Scalar>(1.0) / tan(acos(std::max(lb, std::min(ub, dot(d0,d1) ))));
191
192 heh2 = Base::mesh_.next_halfedge_handle(heh1);
193 p2 = &Base::mesh_.point(Base::mesh_.to_vertex_handle(heh2));
194 d0 = (*p0 - *p2); normalize(d0);
195 d1 = (*p1 - *p2); normalize(d1);
196 weight += static_cast<typename Mesh::Scalar>(1.0) / tan(acos(std::max(lb, std::min(ub, dot(d0,d1) ))));
197
198 Base::mesh_.property(edge_weights_, *e_it) = weight;
199 Base::mesh_.property(vertex_weights_, v0) += weight;
200 Base::mesh_.property(vertex_weights_, v1) += weight;
201 }
202 break;
203 }
204 }
205
206
207 // invert vertex weights:
208 // before: sum of edge weights
209 // after: one over sum of edge weights
210 for (v_it=Base::mesh_.vertices_begin(); v_it!=v_end; ++v_it)
211 {
212 weight = Base::mesh_.property(vertex_weights_, *v_it);
213 if (weight)
214 Base::mesh_.property(vertex_weights_, *v_it) = static_cast<typename Mesh::Scalar>(1.0) / weight;
215 }
216}
217
218
219
220//=============================================================================
221} // namespace Smoother
222} // namespace OpenMesh
223//=============================================================================
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
@ Normal
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:82
VectorT< Scalar, DIM > & normalize(VectorT< Scalar, DIM > &_v)
non-member normalize
Definition: Vector11T.hh:769
Scalar dot(const VectorT< Scalar, DIM > &_v1, const VectorT< Scalar, DIM > &_v2)
symmetric version of the dot product
Definition: Vector11T.hh:725
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Kernel::Scalar Scalar
Scalar type.
Definition: PolyMeshT.hh:110
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:114
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137
Kernel::EdgeIter EdgeIter
Scalar type.
Definition: PolyMeshT.hh:145
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
Kernel::VertexIter VertexIter
Scalar type.
Definition: PolyMeshT.hh:143

Project OpenMesh, ©  Visual Computing Institute, RWTH Aachen. Documentation generated using doxygen .