Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_T4MESH_UTIL_T4MESH_REMOVE_REDUDANT_NODES_H
00002 #define OPENTISSUE_CORE_CONTAINERS_T4MESH_UTIL_T4MESH_REMOVE_REDUDANT_NODES_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/collision/spatial_hashing/spatial_hashing.h>
00013
00014 namespace OpenTissue
00015 {
00016 namespace t4mesh
00017 {
00018
00019 namespace detail
00020 {
00021
00028 template<typename volume_mesh, typename point_container>
00029 class t4mesh_node_collision_policy
00030 {
00031 public:
00032
00033 typedef typename volume_mesh::node_type node_type;
00034 typedef typename node_type::vector3_type vector3_type;
00035 typedef typename vector3_type::value_type real_type;
00036 typedef int index_type;
00037 typedef node_type data_type;
00038 typedef node_type query_type;
00039 typedef OpenTissue::spatial_hashing::GridHashFunction hash_function;
00040
00041 typedef OpenTissue::spatial_hashing::Grid< vector3_type, OpenTissue::math::Vector3<int>, data_type, hash_function> hash_grid;
00042
00043 typedef std::list< data_type* > result_container;
00044
00045 real_type m_precision;
00046 point_container * m_points;
00047
00048 public:
00049
00050 t4mesh_node_collision_policy()
00051 : m_precision(0.01)
00052 {}
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 vector3_type position ( data_type const & data ) const
00073 {
00074 assert( m_points || !"t4mesh_node_collision_policy::position(): points container was null ");
00075 return (*m_points)[data.idx()];
00076 }
00077
00078 vector3_type min_coord( query_type const & query ) const
00079 {
00080 assert( m_points || !"t4mesh_node_collision_policy::min_coord(): points container was null ");
00081 return vector3_type((*m_points)[query.idx()] - vector3_type(m_precision,m_precision,m_precision));
00082 }
00083
00084 vector3_type max_coord( query_type const & query ) const
00085 {
00086 assert( m_points || !"t4mesh_node_collision_policy::max_coord(): points container was null ");
00087 return vector3_type((*m_points)[query.idx()] + vector3_type(m_precision,m_precision,m_precision));
00088 }
00089
00090 void reset ( result_container & results ) { results.clear(); }
00091
00092 void report(data_type const & data, query_type const & query, result_container & results)
00093 {
00094 assert( m_points || !"t4mesh_node_collision_policy::report(): points container was null ");
00095
00096 real_type threshold = m_precision*m_precision + math::working_precision<real_type>( );
00097
00098 if(data.idx()==query.idx())
00099 return;
00100
00101 vector3_type d = (*m_points)[query.idx()] - (*m_points)[data.idx()];
00102 real_type tst = d*d;
00103 if( tst < threshold )
00104 results.push_back( const_cast<data_type*>(&data) );
00105 }
00106
00107 };
00108
00109 }
00110
00120 template<typename volume_mesh, typename point_container>
00121 void remove_redundant_nodes(
00122 volume_mesh & A
00123 , point_container const & pointsA
00124 , volume_mesh & B
00125 , point_container & pointsB
00126 , double precision = 10e-7
00127 )
00128 {
00129
00130 typedef typename detail::t4mesh_node_collision_policy<volume_mesh,point_container> policy;
00131 typedef typename volume_mesh::node_type node_type;
00132 typedef typename volume_mesh::node_iterator node_iterator;
00133 typedef typename volume_mesh::tetrahedron_iterator tetrahedron_iterator;
00134 typedef typename policy::result_container result_container;
00135 typedef typename result_container::iterator result_iterator;
00136 typedef OpenTissue::spatial_hashing::PointDataQuery<typename policy::hash_grid,policy> point_query_type;
00137
00138 std::cout << "remove_redundant_nodes(): Initially "
00139 << A.size_nodes()
00140 << " nodes and "
00141 << A.size_tetrahedra()
00142 << " tetrahedra"
00143 << std::endl;
00144
00145 B.clear();
00146
00147
00148 unsigned int N = A.size_nodes();
00149 std::vector<unsigned int> node_lut(N,~0u);
00150
00151 node_iterator a_begin = A.node_begin();
00152 node_iterator a_end = A.node_end();
00153
00154 point_query_type point_query;
00155
00156 point_query.m_precision = precision;
00157 point_query.m_points = const_cast<point_container*>(&pointsA);
00158
00159 point_query.auto_init_settings( a_begin, a_end );
00160 point_query.init_data( a_begin, a_end);
00161
00162 node_iterator a = a_begin;
00163 node_lut[a->idx()] = B.insert(a->m_coord)->idx();
00164 ++a;
00165 for(; a!=a_end; ++a)
00166 {
00167 result_container results;
00168
00169 point_query( *a , results, typename point_query_type::no_collisions_tag());
00170
00171 result_iterator result = results.begin();
00172 result_iterator r_end = results.end();
00173 unsigned int b = ~0u;
00174 for(;result!=r_end;++result)
00175 {
00176
00177 b = node_lut[ (*result)->idx() ];
00178
00179 if(b != ~0u)
00180 break;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 if(b != ~0u)
00195 node_lut[ a->idx() ] = b;
00196 else
00197 node_lut[ a->idx() ] = B.insert(a->m_coord)->idx();
00198 }
00199
00200
00201 {
00202 pointsB.clear();
00203 pointsB.resize( B.size_nodes() );
00204 for(node_iterator a = a_begin; a!=a_end; ++a)
00205 pointsB[ node_lut[a->idx()] ] = pointsA[ a->idx() ];
00206 }
00207
00208
00209 tetrahedron_iterator T = A.tetrahedron_begin();
00210 tetrahedron_iterator end = A.tetrahedron_end();
00211 for(;T!=end;++T)
00212 {
00213 unsigned int idx_i = node_lut[ T->i()->idx() ];
00214 unsigned int idx_j = node_lut[ T->j()->idx() ];
00215 unsigned int idx_k = node_lut[ T->k()->idx() ];
00216 unsigned int idx_m = node_lut[ T->m()->idx() ];
00217
00218 if(idx_i == idx_j)
00219 continue;
00220 if(idx_i == idx_k)
00221 continue;
00222 if(idx_i == idx_m)
00223 continue;
00224
00225 if(idx_j == idx_k)
00226 continue;
00227 if(idx_j == idx_m)
00228 continue;
00229
00230 if(idx_k == idx_m)
00231 continue;
00232
00233 B.insert(idx_i,idx_j,idx_k,idx_m);
00234 }
00235
00236 std::cout << "remove_redundant_nodes(): removed "
00237 << (A.size_nodes() - B.size_nodes())
00238 << " nodes and "
00239 << (A.size_tetrahedra() - B.size_tetrahedra())
00240 << " tetrahedra"
00241 << std::endl;
00242 }
00243
00244 template<typename volume_mesh>
00245 void remove_redundant_nodes(
00246 volume_mesh & A
00247 , volume_mesh & B
00248 , double precision = 10e-7
00249 )
00250 {
00251
00252 typedef default_point_container<volume_mesh> point_container;
00253 point_container pointsA(&A);
00254 point_container pointsB(&B);
00255 remove_redundant_nodes(A,pointsA,B,pointsB,precision);
00256 }
00257
00258 }
00259 }
00260
00261
00262 #endif