54 #include "DiffGeoT.hh" 73 weights_computed_(false),
86 mesh_.remove_property(area_);
87 mesh_.remove_property(gauss_curvature_);
88 mesh_.remove_property(mean_curvature_);
89 mesh_.remove_property(edge_weight_);
99 compute(
unsigned int _post_smoothing_iters)
101 compute_edge_weights();
103 compute_gauss_curvature();
104 compute_mean_curvature();
105 post_smoothing(_post_smoothing_iters);
112 template <
class Mesh>
115 compute_edge_weights()
118 mesh_.add_property(edge_weight_);
121 typename Mesh::EdgeIter e_it, e_end(mesh_.edges_end());
122 typename Mesh::HalfedgeHandle heh2;
126 for (e_it=mesh_.edges_begin(); e_it!=e_end; ++e_it)
128 const typename Mesh::HalfedgeHandle heh0 = mesh_.halfedge_handle(*e_it, 0);
129 const typename Mesh::Point& p0 = mesh_.point(mesh_.to_vertex_handle(heh0));
131 const typename Mesh::HalfedgeHandle heh1 = mesh_.halfedge_handle(*e_it, 1);
132 const typename Mesh::Point& p1 = mesh_.point(mesh_.to_vertex_handle(heh1));
134 heh2 = mesh_.next_halfedge_handle(heh0);
135 const typename Mesh::Point& p2 = mesh_.point(mesh_.to_vertex_handle(heh2));
136 const typename Mesh::Point d0 = (p0 - p2).normalize();
137 const typename Mesh::Point d1 = (p1 - p2).normalize();
138 weight = 1.0 / tan(acos(d0|d1));
140 heh2 = mesh_.next_halfedge_handle(heh1);
141 const typename Mesh::Point& p3 = mesh_.point(mesh_.to_vertex_handle(heh2));
142 const typename Mesh::Point d2 = (p0 - p3).normalize();
143 const typename Mesh::Point d3 = (p1 - p3).normalize();
144 weight += 1.0 / tan(acos(d2|d3));
146 mesh_.property(edge_weight_, *e_it) = weight;
150 weights_computed_ =
true;
157 template <
class Mesh>
163 mesh_.add_property(area_);
166 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
169 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
170 mesh_.property(area_, *v_it) = compute_area(*v_it);
173 area_computed_ =
true;
180 template <
class Mesh>
183 compute_area(VertexHandle _vh)
const 185 typename Mesh::HalfedgeHandle heh0, heh1, heh2;
189 double normPQ, normQR, normPR;
190 double angleP, angleQ, angleR;
192 double ub(0.999), lb(-0.999);
193 const double epsilon( 1e-12 );
197 for (voh_it=mesh_.voh_iter(_vh); voh_it.is_valid(); ++voh_it)
200 heh1 = mesh_.next_halfedge_handle(heh0);
201 heh2 = mesh_.next_halfedge_handle(heh1);
203 if (mesh_.is_boundary(heh0))
continue;
205 P = mesh_.point(mesh_.to_vertex_handle(heh2));
206 Q = mesh_.point(mesh_.to_vertex_handle(heh0));
207 R = mesh_.point(mesh_.to_vertex_handle(heh1));
217 if( normPQ <= epsilon || normQR <= epsilon || normPR <= epsilon )
220 angleP = (PQ | PR) / normPQ / normPR;
221 angleQ = -(PQ | QR) / normPQ / normQR;
222 angleR = (QR | PR) / normQR / normPR;
224 if (angleP > ub) angleP = ub;
else if (angleP < lb) angleP = lb;
225 if (angleQ > ub) angleQ = ub;
else if (angleQ < lb) angleQ = lb;
226 if (angleR > ub) angleR = ub;
else if (angleR < lb) angleR = lb;
228 angleP = acos(angleP);
229 angleQ = acos(angleQ);
230 angleR = acos(angleR);
232 if (angleP >= M_PI_2 || angleQ >= M_PI_2 || angleR >= M_PI_2)
234 if (angleP >= M_PI_2)
235 area += 0.25 * (PQ % PR).norm();
237 area += 0.125 * (PQ % PR).norm();
241 area += 0.125 * (normPR * normPR / tan(angleQ) +
242 normPQ * normPQ / tan(angleR));
253 template <
class Mesh>
256 compute_gauss_curvature()
259 mesh_.add_property(gauss_curvature_);
265 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
274 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
276 if (!mesh_.is_boundary(*v_it))
280 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
282 vv_it2 = vv_it; ++vv_it2;
284 d0 = (mesh_.point(*vv_it) - mesh_.point(*v_it)).normalize();
285 d1 = (mesh_.point(*vv_it2) - mesh_.point(*v_it)).normalize();
287 cos_angle = std::max(lb, std::min(ub, (d0 | d1)));
288 angles += acos(cos_angle);
291 mesh_.property(gauss_curvature_, *v_it) = (2*M_PI-angles) / mesh_.property(area_, *v_it);
297 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
299 if (mesh_.is_boundary(*v_it))
303 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
304 if (!mesh_.is_boundary(*vv_it))
306 curv += mesh_.property(gauss_curvature_, *vv_it);
311 mesh_.property(gauss_curvature_, *v_it) = curv / count;
320 template <
class Mesh>
323 compute_mean_curvature()
326 mesh_.add_property(mean_curvature_);
328 if (!weights_computed_)
329 compute_edge_weights();
335 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
340 typename Mesh::EdgeHandle eh;
345 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
347 if (!mesh_.is_boundary(*v_it))
349 umbrella[0] = umbrella[1] = umbrella[2] = 0.0;
351 for (voh_it=mesh_.voh_iter(*v_it); voh_it.is_valid(); ++voh_it)
353 eh = mesh_.edge_handle(*voh_it);
354 weight = mesh_.property(edge_weight_, eh);
355 umbrella += (mesh_.point(*v_it) - mesh_.point(mesh_.to_vertex_handle(*voh_it))) * weight;
358 mesh_.property(mean_curvature_, *v_it) =
359 umbrella.norm() / (4.0 * mesh_.property(area_, *v_it));
365 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
367 if (mesh_.is_boundary(*v_it))
371 for (vv_it=mesh_.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
372 if (!mesh_.is_boundary(*vv_it))
374 curv += mesh_.property(mean_curvature_, *vv_it);
379 mesh_.property(mean_curvature_, *v_it) = curv / count;
388 template <
class Mesh>
391 post_smoothing(
unsigned int _iters)
398 if (! (weights_computed_ &&
403 std::cerr <<
"DiffGeoT::post_smoothing: something is wrong!\n";
409 typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
413 typename Mesh::EdgeHandle eh;
419 mesh_.add_property(new_gauss);
420 mesh_.add_property(new_mean);
424 for (
unsigned int i=0; i<_iters; ++i)
428 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
430 if (!mesh_.is_boundary(*v_it))
434 for (voh_it=mesh_.voh_iter(*v_it); voh_it.is_valid(); ++voh_it)
436 eh = mesh_.edge_handle(*voh_it);
437 ww += (w = mesh_.property(edge_weight_, eh));
438 mc += w * mesh_.property(mean_curvature_, mesh_.to_vertex_handle(*voh_it));
439 gc += w * mesh_.property(gauss_curvature_, mesh_.to_vertex_handle(*voh_it));
444 mesh_.property(new_mean, *v_it) = mc / ww;
445 mesh_.property(new_gauss, *v_it) = gc / ww;
452 for (v_it=mesh_.vertices_begin(); v_it!=v_end; ++v_it)
454 if (!mesh_.is_boundary(*v_it))
456 mesh_.property(mean_curvature_, *v_it) = mesh_.property(new_mean, *v_it);
458 mesh_.property(gauss_curvature_, *v_it) = mesh_.property(new_gauss, *v_it);
465 mesh_.remove_property(new_gauss);
466 mesh_.remove_property(new_mean);
Kernel::VertexVertexIter VertexVertexIter
Circulator.
Kernel::Point Point
Coordinate type.
bool is_valid() const
The handle is valid iff the index is not negative.
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Kernel::Scalar Scalar
Scalar type.