Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_UTIL_POLYMESH_INTELLIGENT_PATCHER_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_UTIL_POLYMESH_INTELLIGENT_PATCHER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/mesh/polymesh/polymesh.h>
00013
00014 #include <OpenTissue/core/containers/mesh/common/util/mesh_clear_halfedge_tags.h>
00015
00016 #include <OpenTissue/core/geometry/geometry_plane.h>
00017
00018 namespace OpenTissue
00019 {
00020 namespace polymesh
00021 {
00022
00029 template< typename mesh_type >
00030 bool intelligent_patcher( mesh_type & mesh)
00031 {
00032 typedef typename mesh_type::halfedge_iterator halfedge_iterator;
00033 typedef typename mesh_type::vertex_iterator vertex_iterator;
00034 typedef typename mesh_type::halfedge_type halfedge_type;
00035 typedef typename mesh_type::vertex_handle vertex_handle;
00036 typedef typename mesh_type::index_type index_type;
00037
00038 typedef std::vector< vertex_handle > ring_type;
00039 typedef std::vector< ring_type > ring_container;
00040 typedef typename ring_container::iterator ring_iterator;
00041
00042 typedef typename mesh_type::math_types math_types;
00043 typedef typename math_types::vector3_type vector3_type;
00044 typedef typename math_types::real_type real_type;
00045 typedef geometry::Plane<math_types> plane_type;
00046
00047 ring_container rings;
00048
00049
00050 {
00051 mesh::clear_halfedge_tags(mesh);
00052
00053 halfedge_iterator h = mesh.halfedge_begin();
00054 halfedge_iterator hend = mesh.halfedge_end();
00055 for(;h!=hend;++h)
00056 {
00057 index_type i = h->get_handle().get_idx();
00058 if(h->m_tag==1)
00059 continue;
00060 if(is_boundary(*h))
00061 {
00062 ring_type ring;
00063 halfedge_type * loop = &(*h);
00064 halfedge_type * first = loop;
00065 do
00066 {
00067 index_type j = loop->get_handle().get_idx();
00068 assert(loop->m_tag==0 || !"Oh we saw this halfedge before?");
00069 assert(is_boundary(*loop) || !"Oh, this edge must be a boundary, but it was not?");
00070 loop->m_tag = 1;
00071 ring.push_back(loop->get_destination_handle());
00072 loop = &(*(loop->get_next_iterator()));
00073 }while(loop!=first);
00074 if(ring.size()>2)
00075 rings.push_back(ring);
00076 }
00077 else
00078 {
00079 h->m_tag = 1;
00080 }
00081 }
00082 }
00083
00084
00085
00086 unsigned int N = rings.size();
00087 if(N==0)
00088 return true;
00089
00090
00091 std::vector<plane_type> planes;
00092 {
00093 ring_iterator r = rings.begin();
00094 ring_iterator rend = rings.end();
00095 for(;r!=rend;++r)
00096 {
00097 ring_type & ring = (*r);
00098 plane_type plane;
00099 int i=0, j=1, n=r->size();
00100 real_type a = static_cast<real_type>(0.0);
00101 real_type b = static_cast<real_type>(0.0);
00102 real_type c = static_cast<real_type>(0.0);
00103 real_type xc = static_cast<real_type>(0.0);
00104 real_type yc = static_cast<real_type>(0.0);
00105 real_type zc = static_cast<real_type>(0.0);
00106 for(;i<n;++i,j=(j+1)%n)
00107 {
00108 vertex_iterator vi = mesh.get_vertex_iterator( ring[i] );
00109 vertex_iterator vj = mesh.get_vertex_iterator( ring[j] );
00110 real_type xi = vi->m_coord(0);
00111 real_type yi = vi->m_coord(1);
00112 real_type zi = vi->m_coord(2);
00113 real_type xj = vj->m_coord(0);
00114 real_type yj = vj->m_coord(1);
00115 real_type zj = vj->m_coord(2);
00116 a += (yi - yj) * (zi + zj);
00117 b += (zi - zj) * (xi + xj);
00118 c += (xi - xj) * (yi + yj);
00119 xc += xi;
00120 yc += yi;
00121 zc += zi;
00122 }
00123 real_type norm = static_cast<real_type>(std::sqrt(a*a+b*b+c*c));
00124 plane.n()(0) = a / norm;
00125 plane.n()(1) = b / norm;
00126 plane.n()(2) = c / norm;
00127 plane.w() = (plane.n()(0)*xc + plane.n()(0)*yc +plane.n()(0)*zc)/-n;
00128 planes.push_back(plane);
00129 }
00130 }
00131
00132
00133 std::vector< std::vector<ring_type *> > planar_rings;
00134 {
00135 std::vector<bool> used(N);
00136 real_type tolerance = static_cast<real_type>(0.001);
00137 for(int i=0;i<N;++i)
00138 {
00139 if(used[i])
00140 continue;
00141 planar_rings[i].push_back( rings[i] );
00142 used[i] = true;
00143 for(int j=i+1;j<N;++j)
00144 {
00145 real_type tst = planes[i].n()*planes[j].n();
00146 if(tst<tolerance)
00147 {
00148 planar_rings[i].push_back( rings[j] );
00149 used[j] = true;
00150 }
00151 }
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162 return true;
00163 }
00164
00165 }
00166 }
00167
00168
00169 #endif