Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_MESH_PLANE_CLIPPER_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_MESH_PLANE_CLIPPER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/collision/intersect/intersect_line_plane.h>
00013
00014 #include <utility>
00015 #include <list>
00016 #include <map>
00017
00018 namespace OpenTissue
00019 {
00020 namespace mesh
00021 {
00035 template<
00036 typename mesh_type
00037 , typename plane_type
00038 >
00039 void plane_clipper( mesh_type const & mesh, plane_type plane, mesh_type & above, mesh_type & below, double const & tolerance = 10e-6 )
00040 {
00041 typedef typename mesh_type::index_type index_type;
00042 typedef typename mesh_type::vertex_handle vertex_handle;
00043 typedef typename mesh_type::face_handle face_handle;
00044 typedef typename mesh_type::const_vertex_iterator const_vertex_iterator;
00045 typedef typename mesh_type::const_face_iterator const_face_iterator;
00046 typedef typename mesh_type::const_face_vertex_circulator const_face_vertex_circulator;
00047
00048 typedef typename mesh_type::math_types math_types;
00049 typedef typename math_types::value_traits value_traits;
00050 typedef typename math_types::vector3_type vector3_type;
00051 typedef typename math_types::real_type real_type;
00052
00053 assert(tolerance>=0 || !"tolerance was negative!!!");
00054
00055 above.clear();
00056 below.clear();
00057
00058
00059 std::vector<real_type> distances(mesh.size_vertices(),static_cast<real_type>(0.0));
00060
00061 const_vertex_iterator vend = mesh.vertex_end();
00062 const_vertex_iterator v = mesh.vertex_begin();
00063 for(;v!=vend;++v)
00064 {
00065 index_type idx = v->get_handle().get_idx();
00066 distances[idx] = plane.signed_distance(v->m_coord);
00067 if( std::fabs(distances[idx]) <= tolerance)
00068 distances[idx] = 0;
00069 }
00070
00071 std::vector<vertex_handle> v2a_lut(mesh.size_vertices());
00072 std::vector<vertex_handle> v2b_lut(mesh.size_vertices());
00073
00074 typedef std::pair<vertex_handle,vertex_handle> edge_key_type;
00075 std::map<edge_key_type,vertex_handle> e2a_lut;
00076 std::map<edge_key_type,vertex_handle> e2b_lut;
00077
00078 const static unsigned int is_on = 0;
00079 const static unsigned int is_above = 1;
00080 const static unsigned int is_below = 2;
00081
00082 const_face_iterator fend = mesh.face_end();
00083 const_face_iterator f = mesh.face_begin();
00084
00085 for(;f!=fend;++f)
00086 {
00087 unsigned int state = is_on;
00088
00089 const_face_vertex_circulator cur(*f);
00090 for(unsigned int i=0;i<valency(*f);++i,++cur)
00091 {
00092 if(distances[cur->get_handle().get_idx()]>0)
00093 {
00094 state = is_above;
00095 break;
00096 }
00097 if(distances[cur->get_handle().get_idx()]<0)
00098 {
00099 state = is_below;
00100 break;
00101 }
00102 }
00103 if(state==is_on)
00104 continue;
00105
00106 real_type zero = static_cast<real_type>(0.0);
00107 std::list<vertex_handle> handles_above;
00108 std::list<vertex_handle> handles_below;
00109
00110 const_face_vertex_circulator next(cur);++next;
00111 for(unsigned int i=0;i<valency(*f);++i,++cur,++next)
00112 {
00113 index_type cur_idx = cur->get_handle().get_idx();
00114 index_type next_idx = next->get_handle().get_idx();
00115
00116 edge_key_type e_key = std::make_pair(std::min(cur_idx,next_idx),std::max(cur_idx,next_idx) );
00117
00118 real_type O = distances[cur_idx];
00119 real_type D = distances[next_idx];
00120
00121 bool cur_is_above = (O>zero);
00122 bool cur_is_below = (O<zero);
00123 bool cur_is_on = !(cur_is_above || cur_is_below);
00124 bool next_is_above = (D>zero);
00125 bool next_is_below = (D<zero);
00126 bool next_is_on = !(next_is_above || next_is_below);
00127
00128 #define add_cur_to_above() \
00129 if(v2a_lut[cur_idx].is_null()) \
00130 v2a_lut[cur_idx] = above.add_vertex(cur->m_coord); \
00131 handles_above.push_back( v2a_lut[cur_idx] );
00132
00133 #define add_cur_to_below() \
00134 if(v2b_lut[cur_idx].is_null()) \
00135 v2b_lut[cur_idx] = below.add_vertex(cur->m_coord); \
00136 handles_below.push_back( v2b_lut[cur_idx] );
00137
00138 #define add_crossing_to_above(p) \
00139 if(e2a_lut[e_key].is_null()) \
00140 e2a_lut[e_key] = above.add_vertex(p); \
00141 handles_above.push_back( e2a_lut[e_key] );
00142
00143 #define add_crossing_to_below(p) \
00144 if(e2b_lut[e_key].is_null()) \
00145 e2b_lut[e_key] = below.add_vertex(p); \
00146 handles_below.push_back( e2b_lut[e_key] );
00147
00148 if (cur_is_on && next_is_below && state == is_above)
00149 {
00150 add_cur_to_above();
00151 add_cur_to_below();
00152 state = is_below;
00153 }
00154 else if (cur_is_on && next_is_below && state == is_below)
00155 {
00156 add_cur_to_below();
00157 state = is_below;
00158 }
00159 else if (cur_is_on && next_is_above && state == is_above)
00160 {
00161 add_cur_to_above();
00162 state = is_above;
00163 }
00164 else if (cur_is_on && next_is_above && state == is_below)
00165 {
00166 add_cur_to_above();
00167 add_cur_to_below();
00168 state = is_above;
00169 }
00170 else if (cur_is_above && (next_is_above || next_is_on))
00171 {
00172 add_cur_to_above();
00173 state = is_above;
00174 }
00175 else if (cur_is_below && (next_is_below|| next_is_on) )
00176 {
00177 add_cur_to_below();
00178 state = is_below;
00179 }
00180 else if (cur_is_above && next_is_below)
00181 {
00182 add_cur_to_above();
00183 vector3_type p;
00184 OpenTissue::intersect::line_plane(cur->m_coord,next->m_coord,plane,p);
00185
00186 add_crossing_to_above(p);
00187 add_crossing_to_below(p);
00188 state = is_below;
00189 }
00190 else if (cur_is_below && next_is_above)
00191 {
00192 add_cur_to_below();
00193 vector3_type p;
00194 OpenTissue::intersect::line_plane(cur->m_coord,next->m_coord,plane,p);
00195 add_crossing_to_below(p);
00196 add_crossing_to_above(p);
00197 state = is_above;
00198 }
00199 else if (cur_is_on && next_is_on && state == is_above)
00200 {
00201 add_cur_to_above();
00202 }
00203 else if (cur_is_on && next_is_on && state == is_below)
00204 {
00205 add_cur_to_below();
00206 }
00207
00208 #undef add_cur_to_above
00209 #undef add_cur_to_below
00210 #undef add_crossing_to_above
00211 #undef add_crossing_to_below
00212
00213 }
00214 assert( !(handles_above.empty() && handles_below.empty()) || !"Oups no cut faces?");
00215
00216 if(!handles_above.empty())
00217 above.add_face(handles_above.begin(),handles_above.end());
00218 if(!handles_below.empty())
00219 below.add_face(handles_below.begin(),handles_below.end());
00220
00221 handles_above.clear();
00222 handles_below.clear();
00223 }
00224 }
00225
00226 }
00227 }
00228
00229
00230 #endif