61 #include "DiffGeoT.hh" 80 weights_computed_(false),
93 mesh_.remove_property(area_);
94 mesh_.remove_property(gauss_curvature_);
95 mesh_.remove_property(mean_curvature_);
96 mesh_.remove_property(edge_weight_);
103 template <
class Mesh>
106 compute(
unsigned int _post_smoothing_iters)
108 compute_edge_weights();
110 compute_gauss_curvature();
111 compute_mean_curvature();
112 post_smoothing(_post_smoothing_iters);
119 template <
class Mesh>
122 compute_edge_weights()
124 if (!edge_weight_.is_valid())
125 mesh_.add_property(edge_weight_);
128 typename Mesh::EdgeIter e_it, e_end(mesh_.edges_end());
129 typename Mesh::HalfedgeHandle heh2;
133 for (e_it=mesh_.edges_begin(); e_it!=e_end; ++e_it)
135 const typename Mesh::HalfedgeHandle heh0 = mesh_.halfedge_handle(*e_it, 0);
136 const typename Mesh::Point& p0 = mesh_.point(mesh_.to_vertex_handle(heh0));
138 const typename Mesh::HalfedgeHandle heh1 = mesh_.halfedge_handle(*e_it, 1);
139 const typename Mesh::Point& p1 = mesh_.point(mesh_.to_vertex_handle(heh1));
141 heh2 = mesh_.next_halfedge_handle(heh0);
142 const typename Mesh::Point& p2 = mesh_.point(mesh_.to_vertex_handle(heh2));
143 const typename Mesh::Point d0 = (p0 - p2).normalize();
144 const typename Mesh::Point d1 = (p1 - p2).normalize();
145 weight = 1.0 / tan(acos(d0|d1));
147 heh2 = mesh_.next_halfedge_handle(heh1);
148 const typename Mesh::Point& p3 = mesh_.point(mesh_.to_vertex_handle(heh2));
149 const typename Mesh::Point d2 = (p0 - p3).normalize();
150 const typename Mesh::Point d3 = (p1 - p3).normalize();
151 weight += 1.0 / tan(acos(d2|d3));
153 mesh_.property(edge_weight_, *e_it) = weight;
157 weights_computed_ =
true;
164 template <
class Mesh>
170 mesh_.add_property(area_);
173 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
176 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
177 mesh_.property(area_, *v_it) = compute_area(*v_it);
180 area_computed_ =
true;
187 template <
class Mesh>
190 compute_area(VertexHandle _vh)
const 192 typename Mesh::HalfedgeHandle heh0, heh1, heh2;
196 double normPQ, normQR, normPR;
197 double angleP, angleQ, angleR;
199 double ub(0.999), lb(-0.999);
200 const double epsilon( 1e-12 );
204 for (voh_it=mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it)
207 heh1 = mesh_.next_halfedge_handle(heh0);
208 heh2 = mesh_.next_halfedge_handle(heh1);
210 if (mesh_.is_boundary(heh0))
continue;
212 P = mesh_.point(mesh_.to_vertex_handle(heh2));
213 Q = mesh_.point(mesh_.to_vertex_handle(heh0));
214 R = mesh_.point(mesh_.to_vertex_handle(heh1));
224 if( normPQ <= epsilon || normQR <= epsilon || normPR <= epsilon )
227 angleP = (PQ | PR) / normPQ / normPR;
228 angleQ = -(PQ | QR) / normPQ / normQR;
229 angleR = (QR | PR) / normQR / normPR;
231 if (angleP > ub) angleP = ub;
else if (angleP < lb) angleP = lb;
232 if (angleQ > ub) angleQ = ub;
else if (angleQ < lb) angleQ = lb;
233 if (angleR > ub) angleR = ub;
else if (angleR < lb) angleR = lb;
235 angleP = acos(angleP);
236 angleQ = acos(angleQ);
237 angleR = acos(angleR);
239 if (angleP >= M_PI_2 || angleQ >= M_PI_2 || angleR >= M_PI_2)
241 if (angleP >= M_PI_2)
242 area += 0.25 * (PQ % PR).norm();
244 area += 0.125 * (PQ % PR).norm();
248 area += 0.125 * (normPR * normPR / tan(angleQ) +
249 normPQ * normPQ / tan(angleR));
260 template <
class Mesh>
263 compute_gauss_curvature()
265 if (!gauss_curvature_.is_valid())
266 mesh_.add_property(gauss_curvature_);
272 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
281 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
283 if (!mesh_.is_boundary(*v_it))
287 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
289 vv_it2 = vv_it; ++vv_it2;
291 d0 = (mesh_.point(*vv_it) - mesh_.point(*v_it)).normalize();
292 d1 = (mesh_.point(*vv_it2) - mesh_.point(*v_it)).normalize();
294 cos_angle = std::max(lb, std::min(ub, (d0 | d1)));
295 angles += acos(cos_angle);
298 mesh_.property(gauss_curvature_, *v_it) = (2*M_PI-angles) / mesh_.property(area_, *v_it);
304 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
306 if (mesh_.is_boundary(*v_it))
310 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
311 if (!mesh_.is_boundary(*vv_it))
313 curv += mesh_.property(gauss_curvature_, *vv_it);
318 mesh_.property(gauss_curvature_, *v_it) = curv / count;
327 template <
class Mesh>
330 compute_mean_curvature()
332 if (!mean_curvature_.is_valid())
333 mesh_.add_property(mean_curvature_);
335 if (!weights_computed_)
336 compute_edge_weights();
342 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
347 typename Mesh::EdgeHandle eh;
352 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
354 if (!mesh_.is_boundary(*v_it))
356 umbrella[0] = umbrella[1] = umbrella[2] = 0.0;
358 for (voh_it=mesh_.voh_iter(*v_it); voh_it.is_valid(); ++voh_it)
360 eh = mesh_.edge_handle(*voh_it);
361 weight = mesh_.property(edge_weight_, eh);
362 umbrella += (mesh_.point(*v_it) - mesh_.point(mesh_.to_vertex_handle(*voh_it))) * weight;
365 mesh_.property(mean_curvature_, *v_it) =
366 umbrella.norm() / (4.0 * mesh_.property(area_, *v_it));
372 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
374 if (mesh_.is_boundary(*v_it))
378 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
379 if (!mesh_.is_boundary(*vv_it))
381 curv += mesh_.property(mean_curvature_, *vv_it);
386 mesh_.property(mean_curvature_, *v_it) = curv / count;
395 template <
class Mesh>
398 post_smoothing(
unsigned int _iters)
405 if (! (weights_computed_ &&
407 mean_curvature_.is_valid() &&
408 gauss_curvature_.is_valid()) )
410 std::cerr <<
"DiffGeoT::post_smoothing: something is wrong!\n";
416 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
420 typename Mesh::EdgeHandle eh;
426 mesh_.add_property(new_gauss);
427 mesh_.add_property(new_mean);
431 for (
unsigned int i=0; i<_iters; ++i)
435 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
437 if (!mesh_.is_boundary(*v_it))
441 for (voh_it=mesh_.voh_iter(*v_it); voh_it.is_valid(); ++voh_it)
443 eh = mesh_.edge_handle(*voh_it);
444 ww += (w = mesh_.property(edge_weight_, eh));
445 mc += w * mesh_.property(mean_curvature_, mesh_.to_vertex_handle(*voh_it));
446 gc += w * mesh_.property(gauss_curvature_, mesh_.to_vertex_handle(*voh_it));
451 mesh_.property(new_mean, *v_it) = mc / ww;
452 mesh_.property(new_gauss, *v_it) = gc / ww;
459 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
461 if (!mesh_.is_boundary(*v_it))
463 mesh_.property(mean_curvature_, *v_it) = mesh_.property(new_mean, *v_it);
465 mesh_.property(gauss_curvature_, *v_it) = mesh_.property(new_gauss, *v_it);
472 mesh_.remove_property(new_gauss);
473 mesh_.remove_property(new_mean);
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Kernel::VertexVertexIter VertexVertexIter
Circulator.
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Kernel::Point Point
Coordinate type.
Kernel::Scalar Scalar
Scalar type.