00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_UTIL_POLYMESH_TRIANGULATE_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_UTIL_POLYMESH_TRIANGULATE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/geometry_circumscribed_sphere.h>
00013 #include <OpenTissue/core/containers/containers_heap.h>
00014 #include <OpenTissue/core/containers/mesh/polymesh/util/polymesh_dihedral_angle.h>
00015 #include <OpenTissue/core/containers/mesh/polymesh/util/polymesh_edge_flip.h>
00016 #include <OpenTissue/core/geometry/geometry_sphere.h>
00017 #include <OpenTissue/core/math/math_constants.h>
00018
00019 namespace OpenTissue
00020 {
00021 namespace polymesh
00022 {
00023
00027 template< typename mesh_type >
00028 class PolyMeshTriangulate
00029 {
00030 protected:
00031
00032 typedef typename mesh_type::vertex_handle vertex_handle;
00033 typedef typename mesh_type::math_types math_types;
00034 typedef typename math_types::vector3_type vector3_type;
00035 typedef typename math_types::real_type real_type;
00036 typedef typename mesh_type::edge_handle edge_handle;
00037 typedef geometry::Sphere<math_types> sphere_type;
00038
00039 protected:
00040
00041 typedef OpenTissue::containers::Heap<edge_handle,real_type> heap_type;
00042
00043 heap_type m_heap;
00044
00045 public:
00046
00047 PolyMeshTriangulate()
00048 : m_heap()
00049 {}
00050
00051
00052 protected:
00053
00070 real_type compute_minimum_angle(
00071 vector3_type const & v0
00072 , vector3_type const & v1
00073 , vector3_type const & v2
00074 , vector3_type const & v3
00075 )
00076 {
00077 using std::acos;
00078 using std::min;
00079
00080 vector3_type e20 = unit(v2-v0);
00081 vector3_type e10 = unit(v1-v0);
00082 vector3_type e30 = unit(v3-v0);
00083 vector3_type e21 = unit(v2-v1);
00084 vector3_type e32 = unit(v3-v2);
00085
00086 real_type a0 = acos( e10*e20 );
00087 real_type a1 = acos( -e10*e21 );
00088 real_type a2 = math::detail::pi<real_type>() - a0 - a1;
00089
00090 real_type b0 = acos( -e20*e32 );
00091 real_type b1 = acos( e32*e30 );
00092 real_type b2 = math::detail::pi<real_type>() - b0 - b1;
00093
00094 real_type min_a = min( a0 , min ( a1 , a2 ) );
00095 real_type min_b = min( b0 , min ( b1 , b2 ) );
00096
00097 real_type min_angle = min (min_a, min_b);
00098 return min_angle;
00099 }
00100
00119 real_type compute_priority(
00120 vector3_type const & v0
00121 , vector3_type const & v1
00122 , vector3_type const & v2
00123 , vector3_type const & v3
00124 )
00125 {
00126 using std::min;
00127 using std::fabs;
00128
00129 sphere_type S0,S1;
00130 OpenTissue::geometry::compute_circumscribed_sphere( v0, v1, v2, S0);
00131 OpenTissue::geometry::compute_circumscribed_sphere( v0, v2, v3, S1);
00132 real_type eps0 = 0.001*S0.radius();
00133 real_type d0 = S0.signed_distance(v3);
00134 real_type eps1 = 0.001*S1.radius();
00135 real_type d1 = S1.signed_distance(v1);
00136 bool flip = (d0 < -eps0) || (d1 < -eps1);
00137
00138 if(!flip)
00139 return real_type();
00140
00141 real_type i = compute_minimum_angle(v0,v1,v2,v3);
00142 real_type j = compute_minimum_angle(v1,v2,v3,v0);
00143 real_type rel = fabs(j-i) / fabs(i);
00144 return rel;
00145 }
00146
00156 void update_priority( vertex_handle A, vertex_handle B, mesh_type & mesh )
00157 {
00158 edge_handle Eh = mesh.find_edge_handle(A,B);
00159 if(Eh.is_null())
00160 {
00161 std::cerr << "PolyMeshTriangulate::update_priority(): Argh edge handle was null?" << std::endl;
00162 return;
00163 }
00164
00165 typename heap_type::heap_iterator H;
00166 try
00167 {
00168 H = m_heap.get_heap_iterator(Eh);
00169 }catch(std::invalid_argument e)
00170 {
00171 return;
00172 }
00173
00174 typename mesh_type::edge_iterator E = mesh.get_edge_iterator(Eh);
00175 typename mesh_type::halfedge_iterator e = E->get_halfedge0_iterator();
00176
00177 vector3_type & v0 = e->get_destination_iterator()->m_coord;
00178 vector3_type & v1 = e->get_next_iterator()->get_destination_iterator()->m_coord;
00179 vector3_type & v2 = e->get_origin_iterator()->m_coord;
00180 vector3_type & v3 = e->get_twin_iterator()->get_next_iterator()->get_destination_iterator()->m_coord;
00181
00182 H->priority() = compute_priority(v0,v1,v2,v3);
00183 m_heap.heapify(H);
00184 }
00185
00186 public:
00187
00198 void operator()(mesh_type & mesh, double dihedral_angle_tolerance = 5.0)
00199 {
00200 using std::fabs;
00201
00202 m_heap.clear();
00203
00204 real_type dihedral_tolerance = dihedral_angle_tolerance*math::detail::pi<real_type>()/180.0;
00205
00206
00207 for(typename mesh_type::edge_iterator edge = mesh.edge_begin(); edge!= mesh.edge_end(); ++edge)
00208 {
00209 if(is_boundary(*edge))
00210 continue;
00211 real_type radian;
00212 compute_dihedral_angle(*edge,radian);
00213 if( fabs(radian) > dihedral_tolerance )
00214 continue;
00215
00216 edge_handle h = edge->get_handle();
00217 typename heap_type::heap_iterator i = m_heap.push( h );
00218 typename mesh_type::halfedge_iterator e = edge->get_halfedge0_iterator();
00219 vector3_type & v0 = e->get_destination_iterator()->m_coord;
00220 vector3_type & v1 = e->get_next_iterator()->get_destination_iterator()->m_coord;
00221 vector3_type & v2 = e->get_origin_iterator()->m_coord;
00222 vector3_type & v3 = e->get_twin_iterator()->get_next_iterator()->get_destination_iterator()->m_coord;
00223 i->priority() = compute_priority(v0,v1,v2,v3);
00224 }
00225
00226 m_heap.heapify();
00227
00228 real_type stop_tolerance = 0.01;
00229 unsigned int cnt_flips = 0;
00230 bool forever = true;
00231 do
00232 {
00233 typename heap_type::heap_iterator H = m_heap.top();
00234 edge_handle h = H->get_feature();
00235
00236
00237
00238 if(H->priority() < stop_tolerance )
00239 break;
00240
00241 m_heap.erase(h);
00242
00243 if(!mesh.is_valid_edge_handle(h))
00244 {
00245 std::cerr << "PolyMeshTriangulate::operator(): Invalid edge in heap?" << std::endl;
00246 continue;
00247 }
00248 typename mesh_type::edge_iterator E = mesh.get_edge_iterator(h);
00249 typename mesh_type::halfedge_iterator e = E->get_halfedge0_iterator();
00250
00251 vertex_handle vh0 = e->get_destination_handle();
00252 vertex_handle vh1 = e->get_next_iterator()->get_destination_handle();
00253 vertex_handle vh2 = e->get_origin_handle();
00254 vertex_handle vh3 = e->get_twin_iterator()->get_next_iterator()->get_destination_handle();
00255
00256 if(!edge_flip((*e)))
00257 {
00258 std::cerr << "PolyMeshTriangulate::operator(): Could not flipped edge" << std::endl;
00259 continue;
00260 }
00261
00262 ++cnt_flips;
00263
00264 edge_handle flipped = mesh.find_edge_handle(vh1,vh3);
00265 if(flipped.is_null())
00266 {
00267 std::cerr << "PolyMeshTriangulate::operator(): Could not find the flipped edge" << std::endl;
00268 break;
00269 }
00270 m_heap.push(flipped);
00271
00272 update_priority(vh1,vh3,mesh);
00273 update_priority(vh0,vh1,mesh);
00274 update_priority(vh1,vh2,mesh);
00275 update_priority(vh2,vh3,mesh);
00276 update_priority(vh3,vh0,mesh);
00277
00278 } while (forever);
00279
00280
00281 }
00282
00283 };
00284
00293 template< typename mesh_type >
00294 void triangulate( mesh_type & mesh, double dihedral_angle_tolerance = 5.0 )
00295 {
00296 PolyMeshTriangulate<mesh_type>()(mesh,dihedral_angle_tolerance);
00297 }
00298
00299 }
00300 }
00301
00302
00303 #endif