8 #ifndef VORONOIAREATRIMESHT_HPP_ 9 #define VORONOIAREATRIMESHT_HPP_ 19 template <
class MeshT>
24 obtuse_handling_(_obtuse_handling) {
26 const_cast<MeshT&
>(mesh_).add_property(cotan_weights_,
"VoronoiAreaTriMeshT::CotanWeights");
28 if(obtuse_handling_) {
30 const_cast<MeshT&
>(mesh_).add_property(obtuse_tag_,
"VoronoiAreaTriMeshT::ObtuseTag");
32 tag_obtuse_triangles();
35 compute_cotan_weights();
40 if(obtuse_handling_) {
41 const_cast<MeshT&
>(mesh_).remove_property(obtuse_tag_);
44 const_cast<MeshT&
>(mesh_).remove_property(cotan_weights_);
48 return cotan_weights_;
51 typename MeshT::Scalar get_voronoi_area(
const typename MeshT::VertexHandle& _vh)
const {
53 typename MeshT::Scalar w = 0.0;
56 if(obtuse_handling_) {
57 for(
typename MeshT::ConstVertexFaceIter cvf_it = mesh_.cvf_iter(_vh),
58 cvf_end = mesh_.cvf_end(_vh); cvf_it != cvf_end; ++cvf_it) {
59 if(is_obtuse(*cvf_it)) {
66 for(
typename MeshT::ConstVertexOHalfedgeIter cvoh_it = mesh_.cvoh_iter(_vh),
67 cvoh_end = mesh_.cvoh_end(_vh); cvoh_it != cvoh_end; ++cvoh_it) {
73 const typename MeshT::FaceHandle fh = mesh_.face_handle(*cvoh_it);
88 w += voronoi_area(*cvoh_it);
97 inline typename MeshT::Scalar area(
const typename MeshT::FaceHandle& _fh)
const {
99 typename MeshT::ConstFaceVertexIter cfv_it = mesh_.cfv_iter(_fh);
101 const typename MeshT::Point& p0 = mesh_.point(*cfv_it); ++cfv_it;
102 const typename MeshT::Point& p1 = mesh_.point(*cfv_it); ++cfv_it;
103 const typename MeshT::Point& p2 = mesh_.point(*cfv_it);
105 return ((p1 - p0) % (p2 - p0)).norm() * 0.5;
108 inline typename MeshT::Scalar voronoi_area(
const typename MeshT::HalfedgeHandle& _heh)
const {
110 if(mesh_.is_boundary(_heh))
return 0.0;
112 const typename MeshT::Normal e = mesh_.point(mesh_.to_vertex_handle(_heh)) -
113 mesh_.point(mesh_.from_vertex_handle(_heh));
115 return (1.0/8.0) * mesh_.property(cotan_weights_, mesh_.edge_handle(_heh)) * (e | e);
118 void tag_obtuse_triangles()
const {
120 for(
typename MeshT::ConstFaceIter f_it = mesh_.faces_begin(),
121 f_end = mesh_.faces_end(); f_it != f_end; ++f_it) {
123 typename MeshT::ConstFaceVertexIter cfv_it = mesh_.cfv_iter(*f_it);
125 const typename MeshT::Point& p0 = mesh_.point(*cfv_it); ++cfv_it;
126 const typename MeshT::Point& p1 = mesh_.point(*cfv_it); ++cfv_it;
127 const typename MeshT::Point& p2 = mesh_.point(*cfv_it);
129 const_cast<MeshT&
>(mesh_).property(obtuse_tag_, *f_it) = (
130 (((p1 - p0)|(p2 - p0)) < 0) ||
131 (((p2 - p1)|(p0 - p1)) < 0) ||
132 (((p0 - p2)|(p1 - p0)) < 0));
137 void compute_cotan_weights()
const {
139 for(
typename MeshT::ConstEdgeIter e_it = mesh_.edges_begin(),
140 e_end = mesh_.edges_end(); e_it != e_end; ++e_it) {
142 const typename MeshT::Scalar w = cotan_weight(mesh_.halfedge_handle(*e_it, 0)) +
143 cotan_weight(mesh_.halfedge_handle(*e_it, 1));
145 const_cast<MeshT&
>(mesh_).property(cotan_weights_, *e_it) = w;
149 typename MeshT::Scalar cotan_weight(
const typename MeshT::HalfedgeHandle& _he)
const {
154 const typename MeshT::Normal e0 = (mesh_.point(mesh_.to_vertex_handle(_he)) -
155 mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_he)))).normalized();
157 const typename MeshT::Normal e1 = (mesh_.point(mesh_.from_vertex_handle(_he)) -
158 mesh_.point(mesh_.to_vertex_handle(mesh_.next_halfedge_handle(_he)))).normalized();
160 const typename MeshT::Scalar cos_a = (e0 | e1);
161 const typename MeshT::Scalar sin_a = (e0 % e1).norm();
163 return cos_a / sin_a;
166 inline bool is_obtuse(
const typename MeshT::FaceHandle& _fh)
const {
167 return mesh_.property(obtuse_tag_, _fh);
171 const bool obtuse_handling_;
Add normals to mesh item (vertices/faces)
Implementation of Voronoi area computation as described in "Discrete Differential-Geometry Operators ...