00001 #ifndef OPENTISSUE_CORE_CONTAINERS_T4MESH_T4MESH_H
00002 #define OPENTISSUE_CORE_CONTAINERS_T4MESH_T4MESH_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/t4mesh/t4mesh_t4node.h>
00013 #include <OpenTissue/core/containers/t4mesh/t4mesh_t4tetrahedron.h>
00014 #include <OpenTissue/core/containers/t4mesh/t4mesh_core_access.h>
00015 #include <OpenTissue/utility/utility_index_iterator.h>
00016 #include <OpenTissue/core/math/math_constants.h>
00017
00018 #include <vector>
00019 #include <list>
00020 #include <cassert>
00021
00022 namespace OpenTissue
00023 {
00024 namespace t4mesh
00025 {
00026 namespace detail
00027 {
00028
00049 template<
00050 typename M
00051 , typename N
00052 , typename T
00053 >
00054 class T4Mesh
00055 {
00056 public:
00057
00058 typedef M math_types;
00059 typedef N node_traits;
00060 typedef T tetrahedron_traits;
00061 typedef T4Mesh<M,N,T> mesh_type;
00062 typedef T4Node<mesh_type> node_type;
00063 typedef T4Tetrahedron<mesh_type> tetrahedron_type;
00064 typedef size_t index_type;
00065
00072 static index_type const & undefined()
00073 {
00074 static index_type value = math::detail::highest<index_type>();
00075 return value;
00076 }
00077
00078 protected:
00079
00080 typedef std::vector< node_type > node_container;
00081 typedef std::vector< tetrahedron_type > tetrahedra_container;
00082
00083 protected:
00084
00085 node_container m_nodes;
00086 tetrahedra_container m_tetrahedra;
00087
00088 public:
00089
00090 typedef OpenTissue::utility::IndexIterator<index_type, tetrahedra_container> tetrahedron_iterator;
00091 typedef OpenTissue::utility::IndexIterator<index_type, tetrahedra_container> const_tetrahedron_iterator;
00092
00093 tetrahedron_iterator tetrahedron_begin() { return tetrahedron_iterator( m_tetrahedra, 0 ); }
00094 tetrahedron_iterator tetrahedron_end() { return tetrahedron_iterator( m_tetrahedra, size_tetrahedra() ); }
00095 const_tetrahedron_iterator tetrahedron_begin() const { return const_tetrahedron_iterator( m_tetrahedra, 0 ); }
00096 const_tetrahedron_iterator tetrahedron_end() const { return const_tetrahedron_iterator( m_tetrahedra, size_tetrahedra() ); }
00097
00098 typedef OpenTissue::utility::IndexIterator<index_type, node_container> node_iterator;
00099 typedef OpenTissue::utility::IndexIterator<index_type, node_container> const_node_iterator;
00100
00101 node_iterator node_begin() { return node_iterator( m_nodes, 0 ); }
00102 node_iterator node_end() { return node_iterator( m_nodes, size_nodes() ); }
00103 const_node_iterator node_begin() const { return const_node_iterator( m_nodes, 0 ); }
00104 const_node_iterator node_end() const { return const_node_iterator( m_nodes, size_nodes() ); }
00105
00106 public:
00107
00108 T4Mesh()
00109 : m_nodes()
00110 , m_tetrahedra()
00111 {}
00112
00113
00114 T4Mesh( T4Mesh const & cpy)
00115 {
00116 *this = cpy;
00117 }
00118
00119 T4Mesh & operator=(T4Mesh const & rhs)
00120 {
00121 this->m_nodes = rhs.m_nodes;
00122 this->m_tetrahedra = rhs.m_tetrahedra;
00123 for(node_iterator n = this->node_begin();n!=this->node_end();++n)
00124 t4mesh_core_access::set_owner( (*n) , this );
00125 for(tetrahedron_iterator t = this->tetrahedron_begin();t!=this->tetrahedron_end();++t)
00126 t4mesh_core_access::set_owner( (*t) , this );
00127 return (*this);
00128 }
00129
00130
00131 public:
00132
00133 void clear()
00134 {
00135 m_nodes.clear();
00136 m_tetrahedra.clear();
00137 }
00138
00139 node_iterator node(index_type idx)
00140 {
00141 if(!(idx>=0 && idx<size_nodes()))
00142 throw std::out_of_range("T4Mesh::node(idx): idx out of range");
00143 return node_iterator(m_nodes,idx);
00144 }
00145
00146 const_node_iterator const_node(index_type idx) const
00147 {
00148 if(!(idx>=0 && idx<size_nodes()))
00149 throw std::out_of_range("T4Mesh::const_node(idx): idx out of range");
00150 return const_node_iterator(m_nodes,idx);
00151 }
00152
00153 tetrahedron_iterator tetrahedron(index_type idx)
00154 {
00155 if(!(idx>=0 && idx<size_tetrahedra()))
00156 throw std::out_of_range("T4Mesh::tetrahedron(idx): idx out of range");
00157 return tetrahedron_iterator(m_tetrahedra,idx);
00158 }
00159
00160 const_tetrahedron_iterator tetrahedron(index_type idx)const
00161 {
00162 if(!(idx>=0 && idx<size_tetrahedra()))
00163 throw std::out_of_range("T4Mesh::tetrahedron(idx): idx out of range");
00164 return const_tetrahedron_iterator(m_tetrahedra,idx);
00165 }
00166
00167 size_t size_nodes() const { return m_nodes.size(); }
00168 size_t size_tetrahedra() const { return m_tetrahedra.size(); }
00169
00170 public:
00171
00178 node_iterator insert()
00179 {
00180 m_nodes.push_back( node_type() );
00181 node_type & nd = m_nodes.back();
00182 t4mesh_core_access::set_index( nd, size_nodes()-1 );
00183 t4mesh_core_access::set_owner( nd, this );
00184 return node_iterator(m_nodes, nd.idx());
00185 }
00186
00195 template<typename vector3_type>
00196 node_iterator insert(vector3_type const & coord)
00197 {
00198 node_iterator node = insert();
00199 node->m_coord = coord ;
00200 return node;
00201 }
00202
00210 tetrahedron_iterator insert(
00211 index_type i,
00212 index_type j,
00213 index_type k,
00214 index_type m
00215 )
00216 {
00217 return insert(
00218 node_iterator(m_nodes,i),
00219 node_iterator(m_nodes,j),
00220 node_iterator(m_nodes,k),
00221 node_iterator(m_nodes,m)
00222 );
00223 }
00224
00225 tetrahedron_iterator insert(
00226 node_iterator i,
00227 node_iterator j,
00228 node_iterator k,
00229 node_iterator m
00230 )
00231 {
00232 verify_nodes(i,j,k,m);
00233
00234 assert(find(i,j,k,m)==tetrahedron_end() || !"T4Mesh::insert(): Tetrahedron already exists in mesh");
00235
00236 m_tetrahedra.push_back( tetrahedron_type() );
00237 tetrahedron_type & t = m_tetrahedra.back();
00238
00239 t4mesh_core_access::set_index( t, size_tetrahedra() - 1 );
00240 t4mesh_core_access::set_owner( t, this );
00241 t4mesh_core_access::set_node0( t, i->idx() );
00242 t4mesh_core_access::set_node1( t, j->idx() );
00243 t4mesh_core_access::set_node2( t, k->idx() );
00244 t4mesh_core_access::set_node3( t, m->idx() );
00245
00246 t4mesh_core_access::tetrahedra_push_back( *i, t.idx() );
00247 t4mesh_core_access::tetrahedra_push_back( *j, t.idx() );
00248 t4mesh_core_access::tetrahedra_push_back( *k, t.idx() );
00249 t4mesh_core_access::tetrahedra_push_back( *m, t.idx() );
00250
00251 return tetrahedron_iterator(m_tetrahedra, t.idx());
00252 }
00253
00265 tetrahedron_iterator find(
00266 node_iterator i,
00267 node_iterator j,
00268 node_iterator k,
00269 node_iterator m
00270 ) const
00271 {
00272 verify_nodes(i,j,k,m);
00273
00274 typename node_type::tetrahedron_circulator tit = i->begin();
00275 for(;tit!=i->end();++tit)
00276 {
00277 if(
00278 tit->node_idx(0) == i->idx() &&
00279 tit->node_idx(1) == j->idx() &&
00280 tit->node_idx(2) == k->idx() &&
00281 tit->node_idx(3) == m->idx()
00282 )
00283 return tetrahedron_iterator(m_tetrahedra,tit->idx());
00284 }
00285 return tetrahedron_iterator(m_tetrahedra,size_tetrahedra());
00286 }
00287
00295 tetrahedron_iterator erase(tetrahedron_iterator & where)
00296 {
00297 verify_tetrahedron(where);
00298
00299 tetrahedron_iterator I = tetrahedron(size_tetrahedra()-1);
00300 tetrahedron_iterator last(m_tetrahedra,I->idx());
00301 if(where!=last)
00302 {
00303 this->swap(where,last);
00304 }
00305 this->unlink(last);
00306
00307
00308
00309
00310 m_tetrahedra.pop_back();
00311 return where;
00312 }
00313
00314 protected:
00315
00319 void unlink(tetrahedron_iterator & I)
00320 {
00321 verify_tetrahedron(I);
00322
00323 node_iterator i = I->i();
00324 node_iterator j = I->j();
00325 node_iterator k = I->k();
00326 node_iterator m = I->m();
00327
00328 verify_nodes(i,j,k,m);
00329
00330 t4mesh_core_access::tetrahedra_remove( *i, I->idx() );
00331 t4mesh_core_access::tetrahedra_remove( *j, I->idx() );
00332 t4mesh_core_access::tetrahedra_remove( *k, I->idx() );
00333 t4mesh_core_access::tetrahedra_remove( *m, I->idx() );
00334
00335 t4mesh_core_access::set_node0( *I, this->undefined());
00336 t4mesh_core_access::set_node1( *I, this->undefined());
00337 t4mesh_core_access::set_node2( *I, this->undefined());
00338 t4mesh_core_access::set_node3( *I, this->undefined());
00339 }
00340
00344 void link(
00345 tetrahedron_iterator & I
00346 , node_iterator & i
00347 , node_iterator & j
00348 , node_iterator & k
00349 , node_iterator & m
00350 )
00351 {
00352 verify_tetrahedron(I);
00353
00354 if(I->node_idx(0)!=this->undefined())
00355 throw std::invalid_argument("T4Mesh::link(): node 0 on T was not undefined");
00356 if(I->node_idx(1)!=this->undefined())
00357 throw std::invalid_argument("T4Mesh::link(): node 1 on T was not undefined");
00358 if(I->node_idx(2)!=this->undefined())
00359 throw std::invalid_argument("T4Mesh::link(): node 2 on T was not undefined");
00360 if(I->node_idx(3)!=this->undefined())
00361 throw std::invalid_argument("T4Mesh::link(): node 3 on T was not undefined");
00362
00363 verify_nodes(i,j,k,m);
00364
00365 t4mesh_core_access::tetrahedra_push_back( *i, I->idx() );
00366 t4mesh_core_access::tetrahedra_push_back( *j, I->idx() );
00367 t4mesh_core_access::tetrahedra_push_back( *k, I->idx() );
00368 t4mesh_core_access::tetrahedra_push_back( *m, I->idx() );
00369
00370 t4mesh_core_access::set_node0( *I, i->idx() );
00371 t4mesh_core_access::set_node1( *I, j->idx() );
00372 t4mesh_core_access::set_node2( *I, k->idx() );
00373 t4mesh_core_access::set_node3( *I, m->idx() );
00374 }
00375
00382 void swap(tetrahedron_iterator & A,tetrahedron_iterator & B)
00383 {
00384 if(A==B)
00385 throw std::invalid_argument("T4Mesh::swap(A,B): A and B were the same");
00386
00387 verify_tetrahedron(A);
00388 verify_tetrahedron(B);
00389
00390 index_type Aidx = A->idx();
00391 index_type Bidx = B->idx();
00392
00393 node_iterator Ai = A->i();
00394 node_iterator Aj = A->j();
00395 node_iterator Ak = A->k();
00396 node_iterator Am = A->m();
00397
00398 verify_nodes(Ai,Aj,Ak,Am);
00399
00400 node_iterator Bi = B->i();
00401 node_iterator Bj = B->j();
00402 node_iterator Bk = B->k();
00403 node_iterator Bm = B->m();
00404
00405 verify_nodes(Bi,Bj,Bk,Bm);
00406
00407
00408
00409 unlink(A);
00410 unlink(B);
00411
00412
00413 tetrahedron_traits * TA = &(*A);
00414 tetrahedron_traits tmp;
00415 tetrahedron_traits * TB = &(*B);
00416 tmp = (*TA);
00417 (*TA) = (*TB);
00418 (*TB) = tmp;
00419
00420
00421 t4mesh_core_access::set_index(*A, Aidx);
00422 t4mesh_core_access::set_index(*B, Bidx);
00423
00424 link(A,Bi,Bj,Bk,Bm);
00425 link(B,Ai,Aj,Ak,Am);
00426 }
00427
00428 protected:
00429
00430 void verify_nodes(
00431 node_iterator const & i
00432 , node_iterator const & j
00433 , node_iterator const & k
00434 , node_iterator const & m
00435 ) const
00436 {
00437 if(i->owner()!=this)
00438 {
00439 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): i did not belong to this mesh");
00440 }
00441 if(j->owner()!=this)
00442 {
00443 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): j did not belong to this mesh");
00444 }
00445 if(k->owner()!=this)
00446 {
00447 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): k did not belong to this mesh");
00448 }
00449 if(m->owner()!=this)
00450 {
00451 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): l did not belong to this mesh");
00452 }
00453 if(!( i->idx()>=0 && i->idx()< size_nodes() ) )
00454 {
00455 throw std::out_of_range("T4MEsh::verify_nodes(i,j,k,m): index value of i was out of range");
00456 }
00457 if(!( j->idx()>=0 && j->idx()< size_nodes() ) )
00458 {
00459 throw std::out_of_range("T4MEsh::verify_nodes(i,j,k,m): index value of j was out of range");
00460 }
00461 if(!( k->idx()>=0 && k->idx()< size_nodes() ) )
00462 {
00463 throw std::out_of_range("T4MEsh::verify_nodes(i,j,k,m): index value of k was out of range");
00464 }
00465 if(!( m->idx()>=0 && m->idx()< size_nodes() ) )
00466 {
00467 throw std::out_of_range("T4MEsh::verify_nodes(i,j,k,m): index value of m was out of range");
00468 }
00469 if(i==j)
00470 {
00471 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): i and j was equal");
00472 }
00473 if(i==k)
00474 {
00475 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): i and k was equal");
00476 }
00477 if(i==m)
00478 {
00479 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): i and m was equal");
00480 }
00481 if(j==k)
00482 {
00483 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): j and k was equal");
00484 }
00485 if(j==m)
00486 {
00487 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): j and m was equal");
00488 }
00489 if(k==m)
00490 {
00491 throw std::logic_error("T4MEsh::verify_nodes(i,j,k,m): j and m was equal");
00492 }
00493 }
00494
00495 void verify_tetrahedron(tetrahedron_iterator const & I)const
00496 {
00497 if( !( (I->idx() >=0)&&(I->idx() < size_tetrahedra()) ) )
00498 throw std::out_of_range("T4MEsh::verify_tetrahedron(I): index was out of range");
00499
00500 if(I->owner()!=this)
00501 {
00502 throw std::logic_error("T4MEsh::verify_tetrahedron(I): I did not belong to this mesh");
00503 }
00504 }
00505
00506 };
00507
00508 }
00509 }
00510 }
00511
00512
00513 #endif