00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef VORONOITESSELLATION_HPP_
00031 #define VORONOITESSELLATION_HPP_
00032
00033 #include "UblasCustomFunctions.hpp"
00034 #include "TetrahedralMesh.hpp"
00035 #include "VoronoiCell.hpp"
00036
00037 #include <cmath>
00038 #include <vector>
00039
00040 template<unsigned DIM>
00041 class VoronoiTessellation
00042 {
00043 private:
00044 friend class TestVoronoiTessellation;
00045 friend class InventorVoronoiWriter;
00046
00047 TetrahedralMesh<DIM,DIM>& mrMesh;
00051 std::vector< c_vector<double,DIM>* > mVertices;
00055 std::vector< Face<DIM>* > mFaces;
00059 std::vector< VoronoiCell > mVoronoiCells;
00060
00061
00062 class VertexAndAngle
00063 {
00064 public:
00065 c_vector< double ,DIM >* mpVertex;
00066 double mAngle;
00067 bool operator<(const VertexAndAngle& other) const
00068 {
00069 return mAngle < other.mAngle;
00070 }
00071 };
00072
00073 void GenerateVerticesFromElementCircumcentres();
00074
00080 double ReturnPolarAngle(double x, double y) const;
00081
00082 void Initialise(TetrahedralMesh<2,2>& rMesh);
00083 void Initialise(TetrahedralMesh<3,3>& rMesh);
00084
00085
00086 public:
00087
00088
00089
00090
00091
00092 VoronoiTessellation(TetrahedralMesh<DIM,DIM>& rMesh);
00093
00094 ~VoronoiTessellation();
00095
00096
00097
00098
00099
00100
00101
00102 const VoronoiCell& rGetCell(unsigned index) const;
00103 const Face<DIM>* GetFace(unsigned index) const;
00104 unsigned GetNumFaces();
00105
00106 double GetFaceArea(unsigned index) const;
00107 double GetFacePerimeter(unsigned index) const;
00108
00109 double GetEdgeLength(unsigned nodeIndex1, unsigned nodeIndex2) const;
00110
00111 unsigned GetNumVertices();
00112 c_vector<double,DIM>* GetVertex(unsigned index);
00113
00114 unsigned GetNumCells();
00115
00116 };
00117
00118
00119 template<unsigned DIM>
00120 VoronoiTessellation<DIM>::VoronoiTessellation(TetrahedralMesh<DIM,DIM>& rMesh)
00121 : mrMesh(rMesh)
00122 {
00123 #define COVERAGE_IGNORE
00124 assert(DIM==2 || DIM==3);
00125 #undef COVERAGE_IGNORE
00126
00127 if(DIM==2)
00128 {
00129 }
00130 else
00131 {
00132 GenerateVerticesFromElementCircumcentres();
00133 mVoronoiCells.resize(rMesh.GetNumAllNodes());
00134 }
00135
00136 Initialise(rMesh);
00137 };
00138
00139
00140 template<unsigned DIM>
00141 void VoronoiTessellation<DIM>::Initialise(TetrahedralMesh<2,2>& rMesh)
00142 {
00143 for(unsigned i=0; i<rMesh.GetNumAllNodes(); i++)
00144 {
00145
00146 Face<DIM>* p_face = new Face<DIM>;
00147 mFaces.push_back(p_face);
00148 }
00149
00150
00151
00152
00153
00154 c_matrix<double, DIM, DIM> jacobian, inverse_jacobian;
00155 double jacobian_det;
00156 for(unsigned i=0; i<mrMesh.GetNumElements(); i++)
00157 {
00158 mrMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00159
00160 c_vector<double,DIM+1> circumsphere = mrMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00161
00162 c_vector<double,DIM>* p_circumcentre = new c_vector<double, DIM>;
00163 for(unsigned j=0; j<DIM; j++)
00164 {
00165 (*p_circumcentre)(j)=circumsphere(j);
00166 }
00167 mVertices.push_back(p_circumcentre);
00168
00169 for(unsigned node_index=0; node_index<DIM+1; node_index++)
00170 {
00171 unsigned node_global_index = mrMesh.GetElement(i)->GetNodeGlobalIndex(node_index);
00172 mFaces[node_global_index]->mVertices.push_back(p_circumcentre);
00173 }
00174 }
00175
00176
00177 for(unsigned i=0; i<mFaces.size(); i++)
00178 {
00179
00180 std::vector< VertexAndAngle > vertices_and_angles;
00181 for(unsigned j=0; j<mFaces[i]->mVertices.size(); j++)
00182 {
00183
00184 VertexAndAngle va;
00185 c_vector<double, DIM> centre_to_vertex;
00186 centre_to_vertex = *(mFaces[i]->mVertices[j]) - mrMesh.GetNode(i)->rGetLocation();
00187 va.mAngle = ReturnPolarAngle(centre_to_vertex(0), centre_to_vertex(1));
00188 va.mpVertex = mFaces[i]->mVertices[j];
00189 vertices_and_angles.push_back(va);
00190 }
00191 std::sort(vertices_and_angles.begin(), vertices_and_angles.end());
00192
00193
00194 Face<DIM>* p_face = new Face<DIM>;
00195 for ( typename std::vector< VertexAndAngle >::iterator vertex_iterator = vertices_and_angles.begin();
00196 vertex_iterator !=vertices_and_angles.end();
00197 vertex_iterator++)
00198 {
00199 p_face->mVertices.push_back(vertex_iterator->mpVertex);
00200 }
00201
00202
00203
00204 delete mFaces[i];
00205 mFaces[i] = p_face;
00206 }
00207 }
00208
00209
00210 template<unsigned DIM>
00211 void VoronoiTessellation<DIM>::Initialise(TetrahedralMesh<3,3>& rMesh)
00212 {
00213 #define COVERAGE_IGNORE
00214 assert(DIM==3);
00215 #undef COVERAGE_IGNORE
00216
00217
00218 for (typename TetrahedralMesh<DIM,DIM>::EdgeIterator edge_iterator = mrMesh.EdgesBegin();
00219 edge_iterator != mrMesh.EdgesEnd();
00220 ++edge_iterator)
00221 {
00222 Node<DIM>* p_node_a = edge_iterator.GetNodeA();
00223 Node<DIM>* p_node_b = edge_iterator.GetNodeB();
00224
00225 if ( p_node_a->IsBoundaryNode() && p_node_b->IsBoundaryNode() )
00226 {
00227
00228 Face<DIM>* p_null_face = new Face<DIM>;
00229 mFaces.push_back(p_null_face);
00230 }
00231 else
00232 {
00233 std::set< unsigned >& node_a_element_indices = p_node_a->rGetContainingElementIndices();
00234 std::set< unsigned >& node_b_element_indices = p_node_b->rGetContainingElementIndices();
00235 std::set< unsigned > edge_element_indices;
00236 std::set_intersection(node_a_element_indices.begin(),
00237 node_a_element_indices.end(),
00238 node_b_element_indices.begin(),
00239 node_b_element_indices.end(),
00240 std::inserter(edge_element_indices, edge_element_indices.begin()));
00241 c_vector<double,DIM> edge_vector = p_node_b->rGetLocation() - p_node_a->rGetLocation();
00242 c_vector<double,DIM> mid_edge = edge_vector*0.5 + p_node_a->rGetLocation();
00243 unsigned element0_index=*(edge_element_indices.begin());
00244 c_vector<double,DIM> basis_vector1 = *(mVertices[element0_index]) - mid_edge;
00245 c_vector<double,DIM> basis_vector2;
00246 basis_vector2[0] = edge_vector[1]*basis_vector1[2] - edge_vector[2]*basis_vector1[1];
00247 basis_vector2[1] = edge_vector[2]*basis_vector1[0] - edge_vector[0]*basis_vector1[2];
00248 basis_vector2[2] = edge_vector[0]*basis_vector1[1] - edge_vector[1]*basis_vector1[0];
00249
00250 std::vector< VertexAndAngle> vertices;
00251
00252
00253
00254 for (std::set< unsigned >::iterator element_index_iterator=edge_element_indices.begin();
00255 element_index_iterator!=edge_element_indices.end();
00256 element_index_iterator++)
00257 {
00258
00259 c_vector< double, DIM > vertex_vector = *(mVertices[*element_index_iterator]) - mid_edge;
00260
00261 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
00262 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
00263
00264
00265 VertexAndAngle va;
00266 va.mAngle = ReturnPolarAngle(local_vertex_dot_basis_vector1, local_vertex_dot_basis_vector2);
00267 va.mpVertex = mVertices[*element_index_iterator];
00268 vertices.push_back(va);
00269 }
00270
00271
00272 std::sort(vertices.begin(), vertices.end());
00273
00274
00275 Face<DIM>* p_face = new Face<DIM>;
00276 for ( typename std::vector< VertexAndAngle >::iterator vertex_iterator = vertices.begin();
00277 vertex_iterator !=vertices.end();
00278 vertex_iterator++)
00279 {
00280 p_face->mVertices.push_back(vertex_iterator->mpVertex);
00281 }
00282
00283
00284 mFaces.push_back(p_face);
00285
00286
00287 if (!p_node_a->IsBoundaryNode())
00288 {
00289 mVoronoiCells[p_node_a->GetIndex()].mFaces.push_back(p_face);
00290 mVoronoiCells[p_node_a->GetIndex()].mOrientations.push_back(true);
00291 mVoronoiCells[p_node_a->GetIndex()].mCellCentre = p_node_a->rGetLocation();
00292 }
00293 if (!p_node_b->IsBoundaryNode())
00294 {
00295 mVoronoiCells[p_node_b->GetIndex()].mFaces.push_back(p_face);
00296 mVoronoiCells[p_node_b->GetIndex()].mOrientations.push_back(false);
00297 mVoronoiCells[p_node_b->GetIndex()].mCellCentre = p_node_b->rGetLocation();
00298 }
00299 }
00300 }
00301 }
00302
00303
00304
00305
00306 template<unsigned DIM>
00307 VoronoiTessellation<DIM>::~VoronoiTessellation()
00308 {
00309
00310 for (typename std::vector< Face<DIM>* >::iterator face_iterator=mFaces.begin();
00311 face_iterator!=mFaces.end();
00312 face_iterator++)
00313 {
00314 delete *face_iterator;
00315 }
00316
00317 for (typename std::vector< c_vector<double,DIM>* >::iterator vertex_iterator=mVertices.begin();
00318 vertex_iterator!=mVertices.end();
00319 vertex_iterator++)
00320 {
00321 delete *vertex_iterator;
00322 }
00323 };
00324
00325 template<unsigned DIM>
00326 void VoronoiTessellation<DIM>::GenerateVerticesFromElementCircumcentres()
00327 {
00328
00329 c_matrix<double, DIM, DIM> jacobian, inverse_jacobian;
00330 double jacobian_det;
00331 for(unsigned i=0; i<mrMesh.GetNumElements(); i++)
00332 {
00333 mrMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00334
00335 c_vector<double,DIM+1> circumsphere = mrMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00336
00337 c_vector<double,DIM>* p_circumcentre = new c_vector<double, DIM>;
00338 for(unsigned j=0; j<DIM; j++)
00339 {
00340 (*p_circumcentre)(j)=circumsphere(j);
00341 }
00342 mVertices.push_back(p_circumcentre);
00343 }
00344 };
00345
00346 template<unsigned DIM>
00347 double VoronoiTessellation<DIM>::ReturnPolarAngle(double x, double y) const
00348 {
00349 if (x==0)
00350 {
00351 if (y>0)
00352 {
00353 return M_PI/2.0;
00354 }
00355 else if (y<0)
00356 {
00357 return -M_PI/2.0;
00358 }
00359 else
00360 {
00361 EXCEPTION("Tried to compute polar angle of (0,0)");
00362 }
00363 }
00364
00365 double angle = atan(y/x);
00366
00367 if (y >= 0 && x < 0 )
00368 {
00369 angle += M_PI;
00370 }
00371 else if (y < 0 && x < 0 )
00372 {
00373 angle -= M_PI;
00374 }
00375 return angle;
00376 };
00377
00378 template<unsigned DIM>
00379 const VoronoiCell& VoronoiTessellation<DIM>::rGetCell(unsigned index) const
00380 {
00381 return mVoronoiCells[index];
00382 };
00383
00384 template<unsigned DIM>
00385 const Face<DIM>* VoronoiTessellation<DIM>::GetFace(unsigned index) const
00386 {
00387 #define COVERAGE_IGNORE
00388 assert(DIM==2);
00389 #undef COVERAGE_IGNORE
00390
00391 return mFaces[index];
00392 };
00393
00394 template<unsigned DIM>
00395 double VoronoiTessellation<DIM>::GetEdgeLength(unsigned nodeIndex1, unsigned nodeIndex2) const
00396 {
00397 #define COVERAGE_IGNORE
00398 assert(DIM==2);
00399 #undef COVERAGE_IGNORE
00400
00401 std::vector< c_vector<double, DIM>* > vertices_1 = mFaces[nodeIndex1]->mVertices;
00402 std::vector< c_vector<double, DIM>* > vertices_2 = mFaces[nodeIndex2]->mVertices;
00403 std::sort(vertices_1.begin(), vertices_1.end());
00404 std::sort(vertices_2.begin(), vertices_2.end());
00405 std::vector< c_vector<double, DIM>* > intersecting_vertices;
00406
00407 set_intersection( vertices_1.begin(), vertices_1.end(),
00408 vertices_2.begin(), vertices_2.end(),
00409 back_inserter(intersecting_vertices) );
00410 #define COVERAGE_IGNORE //Debug code from r3223
00411 if (intersecting_vertices.size() != 2)
00412 {
00413 std::cout<< "node 1 = " << nodeIndex1 << " node 2 = " << nodeIndex2 <<" \n" << std::flush;
00414 std::cout<< "vertices 1 \n" << std::flush;
00415 for (unsigned i=0; i<vertices_1.size(); i++)
00416 {
00417 c_vector<double, DIM> current_vertex = *(vertices_1[i]);
00418 std::cout<< current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00419 }
00420 std::cout<< "vertices 2 \n" << std::flush;
00421 for (unsigned i=0; i<vertices_2.size(); i++)
00422 {
00423 c_vector<double, DIM> current_vertex = *(vertices_2[i]);
00424 std::cout<< current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00425 }
00426 std::cout<< "size of common vertices = " << intersecting_vertices.size() << " \n" << std::flush;
00427 }
00428 #undef COVERAGE_IGNORE
00429 assert(intersecting_vertices.size()==2);
00430
00431 c_vector<double, DIM> edge_vector = mrMesh.GetVectorFromAtoB( *(intersecting_vertices[0]),
00432 *(intersecting_vertices[1]) );
00433
00434 return norm_2(edge_vector);
00435 };
00436
00437 template<unsigned DIM>
00438 double VoronoiTessellation<DIM>::GetFaceArea(unsigned index) const
00439 {
00440 #define COVERAGE_IGNORE
00441 assert(DIM==2);
00442 #undef COVERAGE_IGNORE
00443 Face<DIM>& face= *(mFaces[index]);
00444 assert(face.mVertices.size()>0);
00445
00446 Face<DIM> normalised_face;
00447 std::vector< c_vector<double, DIM> > normalised_vertices;
00448 normalised_vertices.reserve(face.mVertices.size());
00449
00450 c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00451 normalised_vertices.push_back(vertex);
00452
00453 normalised_face.mVertices.push_back( &(normalised_vertices[0]) );
00454
00455 for (unsigned vertex_index=1; vertex_index<face.mVertices.size(); vertex_index++)
00456 {
00457 vertex = mrMesh.GetVectorFromAtoB( *(face.mVertices[0]),
00458 *(face.mVertices[vertex_index]) );
00459 normalised_vertices.push_back(vertex);
00460 normalised_face.mVertices.push_back( &(normalised_vertices.back()) );
00461 }
00462 normalised_face.OrderVerticesAntiClockwise();
00463
00464 return normalised_face.GetArea();
00465 };
00466
00467 template<unsigned DIM>
00468 double VoronoiTessellation<DIM>::GetFacePerimeter(unsigned index) const
00469 {
00470 #define COVERAGE_IGNORE
00471 assert(DIM==2);
00472 #undef COVERAGE_IGNORE
00473 Face<DIM>& face= *(mFaces[index]);
00474 assert(face.mVertices.size()>0);
00475
00476 Face<DIM> normalised_face;
00477 std::vector< c_vector<double, DIM> > normalised_vertices;
00478 normalised_vertices.reserve(face.mVertices.size());
00479
00480 c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00481 normalised_vertices.push_back(vertex);
00482
00483 normalised_face.mVertices.push_back( &(normalised_vertices[0]) );
00484
00485 for (unsigned vertex_index=1; vertex_index<face.mVertices.size(); vertex_index++)
00486 {
00487 vertex = mrMesh.GetVectorFromAtoB( *(face.mVertices[0]),
00488 *(face.mVertices[vertex_index]) );
00489 normalised_vertices.push_back(vertex);
00490 normalised_face.mVertices.push_back( &(normalised_vertices.back()) );
00491 }
00492 normalised_face.OrderVerticesAntiClockwise();
00493
00494 return normalised_face.GetPerimeter();
00495
00496 };
00497
00498 template<unsigned DIM>
00499 unsigned VoronoiTessellation<DIM>::GetNumVertices()
00500 {
00501 return mVertices.size();
00502 }
00503
00504 template<unsigned DIM>
00505 unsigned VoronoiTessellation<DIM>::GetNumFaces()
00506 {
00507 return mFaces.size();
00508 }
00509
00510 template<unsigned DIM>
00511 unsigned VoronoiTessellation<DIM>::GetNumCells()
00512 {
00513 assert(DIM==3);
00514 return mVoronoiCells.size();
00515 }
00516
00517 template<unsigned DIM>
00518 c_vector<double,DIM>* VoronoiTessellation<DIM>::GetVertex(unsigned index)
00519 {
00520 assert(index<mVertices.size());
00521 return mVertices[index];
00522 }
00523
00524 #endif