VoronoiTessellation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #include "VoronoiTessellation.hpp"
00031 
00032 
00034 // Implementation
00036 
00037 
00038 template<unsigned DIM>
00039 VoronoiTessellation<DIM>::VoronoiTessellation(TetrahedralMesh<DIM,DIM>& rMesh)
00040     : mrMesh(rMesh)
00041 {
00042     #define COVERAGE_IGNORE
00043     assert(DIM==2 || DIM==3);
00044     #undef COVERAGE_IGNORE
00045 
00046     if (DIM==3)
00047     {
00048         GenerateVerticesFromElementCircumcentres();
00049         mVoronoiCells.resize(rMesh.GetNumAllNodes());
00050     }
00051 
00052     Initialise(rMesh);
00053 }
00054 
00060 template<>
00061 void VoronoiTessellation<1>::Initialise(TetrahedralMesh<1,1>& rMesh)
00062 {
00063     // No 1D Voronoi tessellation
00064     NEVER_REACHED;
00065 }
00066 
00072 template<>
00073 void VoronoiTessellation<2>::Initialise(TetrahedralMesh<2,2>& rMesh)
00074 {
00075     for (unsigned i=0; i<rMesh.GetNumAllNodes(); i++)
00076     {
00077         // This edge is on the boundary
00078         Face<2> *p_face = new Face<2>;
00079         mFaces.push_back(p_face);
00080     }
00081 
00082     /*
00083      * Loop over elements, for each element calculate circumcentre (=vertex), set that as a
00084      * vertex for each node(=face in 2d) of that element. Also loop over mesh-edges of the
00085      * element and add the vertex as a vertex for that vertex-edge.
00086      */
00087     c_matrix<double, 2, 2> jacobian, inverse_jacobian;
00088     double jacobian_det;
00089     for (unsigned i=0; i<mrMesh.GetNumElements(); i++)
00090     {
00091         mrMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00092 
00093         c_vector<double,3> circumsphere = mrMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00094 
00095         c_vector<double,2> *p_circumcentre = new c_vector<double, 2>;
00096         for (unsigned j=0; j<2; j++)
00097         {
00098             (*p_circumcentre)(j) = circumsphere(j);
00099         }
00100         mVertices.push_back(p_circumcentre);
00101 
00102         for (unsigned node_index=0; node_index<3; node_index++)
00103         {
00104             unsigned node_global_index = mrMesh.GetElement(i)->GetNodeGlobalIndex(node_index);
00105             mFaces[node_global_index]->AddVertex(p_circumcentre);
00106         }
00107     }
00108 
00109     // Reorder mVertices Anticlockwise
00110     for (unsigned i=0; i<mFaces.size(); i++)
00111     {
00112         std::vector<VertexAndAngle<2> > vertices_and_angles;
00113         for (unsigned j=0; j<mFaces[i]->GetNumVertices(); j++)
00114         {
00115             VertexAndAngle<2> va;
00116             c_vector<double, 2> centre_to_vertex = mFaces[i]->rGetVertex(j) - mrMesh.GetNode(i)->rGetLocation();
00117             va.ComputeAndSetAngle(centre_to_vertex(0), centre_to_vertex(1));
00118             va.SetVertex(&(mFaces[i]->rGetVertex(j)));
00119             vertices_and_angles.push_back(va);
00120         }
00121         std::sort(vertices_and_angles.begin(), vertices_and_angles.end());
00122 
00123         // Create face
00124         Face<2> *p_face = new Face<2>;
00125         for (std::vector<VertexAndAngle<2> >::iterator vertex_iterator = vertices_and_angles.begin();
00126              vertex_iterator != vertices_and_angles.end();
00127              vertex_iterator++)
00128         {
00129             p_face->AddVertex(vertex_iterator->GetVertex());
00130         }
00131 
00132         // Add face to list of faces
00133         delete mFaces[i];
00134         mFaces[i] = p_face;
00135     }
00136 }
00137 
00143 template<>
00144 void VoronoiTessellation<3>::Initialise(TetrahedralMesh<3,3>& rMesh)
00145 {
00146     // Loop over each edge
00147     for (TetrahedralMesh<3,3>::EdgeIterator edge_iterator = mrMesh.EdgesBegin();
00148          edge_iterator != mrMesh.EdgesEnd();
00149          ++edge_iterator)
00150     {
00151         Node<3> *p_node_a = edge_iterator.GetNodeA();
00152         Node<3> *p_node_b = edge_iterator.GetNodeB();
00153 
00154         if ( p_node_a->IsBoundaryNode() && p_node_b->IsBoundaryNode() )
00155         {
00156             // This edge is on the boundary
00157             Face<3> *p_null_face = new Face<3>;
00158             mFaces.push_back(p_null_face);
00159         }
00160         else
00161         {
00162             std::set<unsigned>& node_a_element_indices = p_node_a->rGetContainingElementIndices();
00163             std::set<unsigned>& node_b_element_indices = p_node_b->rGetContainingElementIndices();
00164             std::set<unsigned> edge_element_indices;
00165 
00166             std::set_intersection(node_a_element_indices.begin(),
00167                                   node_a_element_indices.end(),
00168                                   node_b_element_indices.begin(),
00169                                   node_b_element_indices.end(),
00170                                   std::inserter(edge_element_indices, edge_element_indices.begin()));
00171 
00172             c_vector<double,3> edge_vector = p_node_b->rGetLocation() - p_node_a->rGetLocation();
00173             c_vector<double,3> mid_edge = edge_vector*0.5 + p_node_a->rGetLocation();
00174 
00175             unsigned element0_index = *(edge_element_indices.begin());
00176 
00177             c_vector<double,3> basis_vector1 = *(mVertices[element0_index]) - mid_edge;
00178 
00179             c_vector<double,3> basis_vector2;
00180             basis_vector2[0] = edge_vector[1]*basis_vector1[2] - edge_vector[2]*basis_vector1[1];
00181             basis_vector2[1] = edge_vector[2]*basis_vector1[0] - edge_vector[0]*basis_vector1[2];
00182             basis_vector2[2] = edge_vector[0]*basis_vector1[1] - edge_vector[1]*basis_vector1[0];
00183 
00184             std::vector<VertexAndAngle<3> > vertices;
00185 
00186             // Loop over each element containing this edge:
00187             // the elements are those containing both nodes of the edge
00188             for (std::set<unsigned>::iterator element_index_iterator = edge_element_indices.begin();
00189                  element_index_iterator != edge_element_indices.end();
00190                  element_index_iterator++)
00191             {
00192                 // Calculate angle
00193                 c_vector<double, 3> vertex_vector = *(mVertices[*element_index_iterator]) - mid_edge;
00194 
00195                 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
00196                 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
00197 
00198                 VertexAndAngle<3> va;
00199                 va.ComputeAndSetAngle(local_vertex_dot_basis_vector1, local_vertex_dot_basis_vector2);
00200                 va.SetVertex(mVertices[*element_index_iterator]);
00201                 vertices.push_back(va);
00202             }
00203 
00204             // Sort vertices by angle
00205             std::sort(vertices.begin(), vertices.end());
00206 
00207             // Create face
00208             Face<3> *p_face = new Face<3>;
00209             for (std::vector<VertexAndAngle<3> >::iterator vertex_iterator = vertices.begin();
00210                  vertex_iterator != vertices.end();
00211                  vertex_iterator++)
00212             {
00213                 p_face->AddVertex(vertex_iterator->GetVertex());
00214             }
00215 
00216             // Add face to list of faces...
00217             mFaces.push_back(p_face);
00218 
00219             // ...and appropriate elements
00220             if (!p_node_a->IsBoundaryNode())
00221             {
00222                 mVoronoiCells[p_node_a->GetIndex()].AddFace(p_face);
00223                 mVoronoiCells[p_node_a->GetIndex()].AddOrientation(true);
00224                 mVoronoiCells[p_node_a->GetIndex()].SetCellCentre(p_node_a->rGetLocation());
00225             }
00226             if (!p_node_b->IsBoundaryNode())
00227             {
00228                 mVoronoiCells[p_node_b->GetIndex()].AddFace(p_face);
00229                 mVoronoiCells[p_node_b->GetIndex()].AddOrientation(false);
00230                 mVoronoiCells[p_node_b->GetIndex()].SetCellCentre(p_node_b->rGetLocation());
00231             }
00232         }
00233     }
00234 }
00235 
00236 template<unsigned DIM>
00237 VoronoiTessellation<DIM>::~VoronoiTessellation()
00238 {
00239     // Delete faces
00240     for (typename std::vector< Face<DIM>* >::iterator face_iterator = mFaces.begin();
00241          face_iterator != mFaces.end();
00242          face_iterator++)
00243     {
00244         delete *face_iterator;
00245     }
00246     // Delete vertices
00247     for (typename std::vector< c_vector<double,DIM>* >::iterator vertex_iterator = mVertices.begin();
00248          vertex_iterator != mVertices.end();
00249          vertex_iterator++)
00250     {
00251         delete *vertex_iterator;
00252     }
00253 }
00254 
00255 template<unsigned DIM>
00256 void VoronoiTessellation<DIM>::GenerateVerticesFromElementCircumcentres()
00257 {
00258     c_matrix<double, DIM, DIM> jacobian, inverse_jacobian;
00259     double jacobian_det;
00260     for (unsigned i=0; i<mrMesh.GetNumElements(); i++)
00261     {
00262         mrMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00263 
00264         c_vector<double,DIM+1> circumsphere = mrMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00265 
00266         c_vector<double,DIM>*  p_circumcentre = new c_vector<double, DIM>;
00267         for (unsigned j=0; j<DIM; j++)
00268         {
00269             (*p_circumcentre)(j)=circumsphere(j);
00270         }
00271         mVertices.push_back(p_circumcentre);
00272     }
00273 }
00274 
00275 template<unsigned DIM>
00276 const VoronoiCell& VoronoiTessellation<DIM>::rGetCell(unsigned index) const
00277 {
00278     return mVoronoiCells[index];
00279 }
00280 
00281 template<unsigned DIM>
00282 const Face<DIM>& VoronoiTessellation<DIM>::rGetFace(unsigned index) const
00283 {
00284     #define COVERAGE_IGNORE
00285     assert(DIM==2);
00286     #undef COVERAGE_IGNORE
00287 
00288     return *(mFaces[index]);
00289 }
00290 
00291 template<unsigned DIM>
00292 double VoronoiTessellation<DIM>::GetEdgeLength(unsigned nodeIndex1, unsigned nodeIndex2) const
00293 {
00294     #define COVERAGE_IGNORE
00295     assert(DIM==2);
00296     #undef COVERAGE_IGNORE
00297 
00298     std::vector< c_vector<double, DIM>* > vertices_1 = mFaces[nodeIndex1]->rGetVertices();
00299     std::vector< c_vector<double, DIM>* > vertices_2 = mFaces[nodeIndex2]->rGetVertices();
00300     std::sort(vertices_1.begin(), vertices_1.end());
00301     std::sort(vertices_2.begin(), vertices_2.end());
00302     std::vector< c_vector<double, DIM>* > intersecting_vertices;
00303 
00304     set_intersection( vertices_1.begin(), vertices_1.end(),
00305                       vertices_2.begin(), vertices_2.end(),
00306                       back_inserter(intersecting_vertices) );
00307 
00308 #define COVERAGE_IGNORE //Debug code from r3223
00309     if (intersecting_vertices.size() != 2)
00310     {
00311         std::cout << "node 1 = " << nodeIndex1 << " node 2 = " << nodeIndex2 << " \n" << std::flush;
00312         std::cout << "vertices 1 \n" << std::flush;
00313         for (unsigned i=0; i<vertices_1.size(); i++)
00314         {
00315             c_vector<double, DIM> current_vertex = *(vertices_1[i]);
00316             std::cout << current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00317         }
00318         std::cout << "vertices 2 \n" << std::flush;
00319         for (unsigned i=0; i<vertices_2.size(); i++)
00320         {
00321             c_vector<double, DIM> current_vertex = *(vertices_2[i]);
00322             std::cout << current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00323         }
00324         std::cout << "size of common vertices = " << intersecting_vertices.size() << " \n" << std::flush;
00325     }
00326 #undef COVERAGE_IGNORE
00327     assert(intersecting_vertices.size()==2);
00328 
00329     c_vector<double, DIM> edge_vector = mrMesh.GetVectorFromAtoB( *(intersecting_vertices[0]),
00330                                                                   *(intersecting_vertices[1]) );
00331 
00332     return norm_2(edge_vector);
00333 }
00334 
00335 template<unsigned DIM>
00336 double VoronoiTessellation<DIM>::GetFaceArea(unsigned index) const
00337 {
00338 #define COVERAGE_IGNORE
00339     assert(DIM==2);
00340 #undef COVERAGE_IGNORE
00341 
00342     Face<DIM>& face = *(mFaces[index]);
00343     assert(face.GetNumVertices() > 0);
00344 
00345     Face<DIM> normalised_face;
00346     std::vector< c_vector<double, DIM> > normalised_vertices;
00347     normalised_vertices.reserve(face.GetNumVertices());
00348 
00349     c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00350     normalised_vertices.push_back(vertex);
00351 
00352     normalised_face.AddVertex( &(normalised_vertices[0]) );
00353 
00354     for (unsigned vertex_index=1; vertex_index<face.GetNumVertices(); vertex_index++)
00355     {
00356         vertex = mrMesh.GetVectorFromAtoB(face.rGetVertex(0), face.rGetVertex(vertex_index));
00357         normalised_vertices.push_back(vertex);
00358         normalised_face.AddVertex( &(normalised_vertices.back()) );
00359     }
00360     normalised_face.OrderVerticesAntiClockwise();
00361 
00362     return normalised_face.GetArea();
00363 }
00364 
00365 template<unsigned DIM>
00366 double VoronoiTessellation<DIM>::GetFacePerimeter(unsigned index) const
00367 {
00368     #define COVERAGE_IGNORE
00369     assert(DIM==2);
00370     #undef COVERAGE_IGNORE
00371 
00372     Face<DIM>& face = *(mFaces[index]);
00373     assert(face.GetNumVertices() > 0);
00374 
00375     Face<DIM> normalised_face;
00376     std::vector< c_vector<double, DIM> > normalised_vertices;
00377     normalised_vertices.reserve(face.GetNumVertices());
00378 
00379     c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00380     normalised_vertices.push_back(vertex);
00381 
00382     normalised_face.AddVertex( &(normalised_vertices[0]) );
00383 
00384     for (unsigned vertex_index=1; vertex_index<face.GetNumVertices(); vertex_index++)
00385     {
00386         vertex = mrMesh.GetVectorFromAtoB(face.rGetVertex(0), face.rGetVertex(vertex_index));
00387         normalised_vertices.push_back(vertex);
00388         normalised_face.AddVertex( &(normalised_vertices.back()) );
00389     }
00390     normalised_face.OrderVerticesAntiClockwise();
00391 
00392     return normalised_face.GetPerimeter();
00393 }
00394 
00395 template<unsigned DIM>
00396 unsigned VoronoiTessellation<DIM>::GetNumVertices() const
00397 {
00398     return mVertices.size();
00399 }
00400 
00401 template<unsigned DIM>
00402 unsigned VoronoiTessellation<DIM>::GetNumFaces() const
00403 {
00404     return mFaces.size();
00405 }
00406 
00407 template<unsigned DIM>
00408 unsigned VoronoiTessellation<DIM>::GetNumCells()
00409 {
00410     assert(DIM==3);
00411     return mVoronoiCells.size();
00412 }
00413 
00414 template<unsigned DIM>
00415 c_vector<double,DIM>* VoronoiTessellation<DIM>::GetVertex(unsigned index)
00416 {
00417     assert(index<mVertices.size());
00418     return mVertices[index];
00419 }
00420 
00421 
00423 // Explicit instantiation
00425 
00426 
00427 template class VoronoiTessellation<1>;
00428 template class VoronoiTessellation<2>;
00429 template class VoronoiTessellation<3>;

Generated on Tue Aug 4 16:10:24 2009 for Chaste by  doxygen 1.5.5