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 #include "VoronoiTessellation.hpp"
00031 #include <list>
00032
00037 template<unsigned DIM>
00038 bool VertexAngleComparison(const std::pair<c_vector<double, DIM>*, double> lhs, const std::pair<c_vector<double, DIM>*, double> rhs)
00039 {
00040 return lhs.second < rhs.second;
00041 }
00042
00044
00046
00047 template<unsigned DIM>
00048 VoronoiTessellation<DIM>::VoronoiTessellation(TetrahedralMesh<DIM,DIM>& rMesh, const std::vector<unsigned> locationIndices)
00049 : mrMesh(rMesh)
00050 {
00051 #define COVERAGE_IGNORE
00052 assert(DIM==2 || DIM==3);
00053 #undef COVERAGE_IGNORE
00054
00055 if (!locationIndices.empty())
00056 {
00057 for (unsigned i=0; i<locationIndices.size(); i++)
00058 {
00059 mLocationIndices.insert(locationIndices[i]);
00060 }
00061 }
00062
00063 Initialise(rMesh);
00064 }
00065
00071 template<>
00072 void VoronoiTessellation<1>::Initialise(TetrahedralMesh<1,1>& rMesh)
00073 {
00074
00075 NEVER_REACHED;
00076 }
00077
00083 template<>
00084 void VoronoiTessellation<2>::Initialise(TetrahedralMesh<2,2>& rMesh)
00085 {
00086
00087 GenerateVerticesFromElementCircumcentres();
00088
00089
00090 for (unsigned i=0; i<rMesh.GetNumAllNodes(); i++)
00091 {
00092 Face<2>* p_face = new Face<2>;
00093 mFaces.push_back(p_face);
00094 }
00095
00096
00097 for (unsigned i=0; i<mrMesh.GetNumElements(); i++)
00098 {
00099 for (unsigned node_index=0; node_index<3; node_index++)
00100 {
00101 unsigned node_global_index = mrMesh.GetElement(i)->GetNodeGlobalIndex(node_index);
00102
00103 if (!mLocationIndices.empty())
00104 {
00105 if (mLocationIndices.find(node_global_index) != mLocationIndices.end())
00106 {
00107 mFaces[node_global_index]->AddVertex(mVertices[i]);
00108 }
00109 }
00110 else
00111 {
00112 mFaces[node_global_index]->AddVertex(mVertices[i]);
00113 }
00114 }
00115 }
00116
00117
00118 for (unsigned i=0; i<mFaces.size(); i++)
00119 {
00120
00121 std::list<std::pair<c_vector<double, 2>*, double> > vertex_angle_list;
00122 for (unsigned j=0; j<mFaces[i]->GetNumVertices(); j++)
00123 {
00124 c_vector<double, 2> centre_to_vertex = mFaces[i]->rGetVertex(j) - mrMesh.GetNode(i)->rGetLocation();
00125 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
00126 std::pair<c_vector<double, 2>*, double> pair(&(mFaces[i]->rGetVertex(j)), angle);
00127 vertex_angle_list.push_back(pair);
00128 }
00129
00130
00131 vertex_angle_list.sort(VertexAngleComparison<2>);
00132
00133
00134 Face<2>* p_face = new Face<2>;
00135 for (std::list<std::pair<c_vector<double, 2>*, double> >::iterator list_iter = vertex_angle_list.begin();
00136 list_iter != vertex_angle_list.end();
00137 ++list_iter)
00138 {
00139 p_face->AddVertex(list_iter->first);
00140 }
00141
00142
00143 delete mFaces[i];
00144 mFaces[i] = p_face;
00145 }
00146 }
00147
00153 template<>
00154 void VoronoiTessellation<3>::Initialise(TetrahedralMesh<3,3>& rMesh)
00155 {
00156
00157 GenerateVerticesFromElementCircumcentres();
00158
00159
00160 mVoronoiCells.resize(rMesh.GetNumAllNodes());
00161
00162
00163 for (TetrahedralMesh<3,3>::EdgeIterator edge_iterator = mrMesh.EdgesBegin();
00164 edge_iterator != mrMesh.EdgesEnd();
00165 ++edge_iterator)
00166 {
00167 Node<3>* p_node_a = edge_iterator.GetNodeA();
00168 Node<3>* p_node_b = edge_iterator.GetNodeB();
00169
00170 if ( p_node_a->IsBoundaryNode() && p_node_b->IsBoundaryNode() )
00171 {
00172
00173 Face<3>* p_null_face = new Face<3>;
00174 mFaces.push_back(p_null_face);
00175 }
00176 else
00177 {
00178 std::set<unsigned>& node_a_element_indices = p_node_a->rGetContainingElementIndices();
00179 std::set<unsigned>& node_b_element_indices = p_node_b->rGetContainingElementIndices();
00180 std::set<unsigned> edge_element_indices;
00181
00182 std::set_intersection(node_a_element_indices.begin(),
00183 node_a_element_indices.end(),
00184 node_b_element_indices.begin(),
00185 node_b_element_indices.end(),
00186 std::inserter(edge_element_indices, edge_element_indices.begin()));
00187
00188 c_vector<double,3> edge_vector = p_node_b->rGetLocation() - p_node_a->rGetLocation();
00189 c_vector<double,3> mid_edge = edge_vector*0.5 + p_node_a->rGetLocation();
00190
00191 unsigned element0_index = *(edge_element_indices.begin());
00192
00193 c_vector<double,3> basis_vector1 = *(mVertices[element0_index]) - mid_edge;
00194
00195 c_vector<double,3> basis_vector2;
00196 basis_vector2[0] = edge_vector[1]*basis_vector1[2] - edge_vector[2]*basis_vector1[1];
00197 basis_vector2[1] = edge_vector[2]*basis_vector1[0] - edge_vector[0]*basis_vector1[2];
00198 basis_vector2[2] = edge_vector[0]*basis_vector1[1] - edge_vector[1]*basis_vector1[0];
00199
00200 std::list<std::pair<c_vector<double, 3>*, double> > vertex_angle_list;
00201
00202
00203
00204 for (std::set<unsigned>::iterator element_index_iterator = edge_element_indices.begin();
00205 element_index_iterator != edge_element_indices.end();
00206 element_index_iterator++)
00207 {
00208
00209 c_vector<double, 3> vertex_vector = *(mVertices[*element_index_iterator]) - mid_edge;
00210
00211 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
00212 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
00213
00214 double angle = atan2(local_vertex_dot_basis_vector2, local_vertex_dot_basis_vector1);
00215
00216 std::pair<c_vector<double, 3>*, double> pair(mVertices[*element_index_iterator], angle);
00217 vertex_angle_list.push_back(pair);
00218 }
00219
00220
00221 vertex_angle_list.sort(VertexAngleComparison<3>);
00222
00223
00224 Face<3>* p_face = new Face<3>;
00225 for (std::list<std::pair<c_vector<double, 3>*, double> >::iterator list_iter = vertex_angle_list.begin();
00226 list_iter != vertex_angle_list.end();
00227 ++list_iter)
00228 {
00229 p_face->AddVertex(list_iter->first);
00230 }
00231
00232
00233 mFaces.push_back(p_face);
00234
00235
00236 if (!p_node_a->IsBoundaryNode())
00237 {
00238 mVoronoiCells[p_node_a->GetIndex()].AddFace(p_face);
00239 mVoronoiCells[p_node_a->GetIndex()].AddOrientation(true);
00240 mVoronoiCells[p_node_a->GetIndex()].SetCellCentre(p_node_a->rGetLocation());
00241 }
00242 if (!p_node_b->IsBoundaryNode())
00243 {
00244 mVoronoiCells[p_node_b->GetIndex()].AddFace(p_face);
00245 mVoronoiCells[p_node_b->GetIndex()].AddOrientation(false);
00246 mVoronoiCells[p_node_b->GetIndex()].SetCellCentre(p_node_b->rGetLocation());
00247 }
00248 }
00249 }
00250 }
00251
00252 template<unsigned DIM>
00253 VoronoiTessellation<DIM>::~VoronoiTessellation()
00254 {
00255
00256 for (typename std::vector< Face<DIM>* >::iterator face_iterator = mFaces.begin();
00257 face_iterator != mFaces.end();
00258 face_iterator++)
00259 {
00260 delete *face_iterator;
00261 }
00262
00263 for (typename std::vector< c_vector<double,DIM>* >::iterator vertex_iterator = mVertices.begin();
00264 vertex_iterator != mVertices.end();
00265 vertex_iterator++)
00266 {
00267 delete *vertex_iterator;
00268 }
00269 }
00270
00271 template<unsigned DIM>
00272 void VoronoiTessellation<DIM>::GenerateVerticesFromElementCircumcentres()
00273 {
00274 c_matrix<double, DIM, DIM> jacobian, inverse_jacobian;
00275 double jacobian_det;
00276 for (unsigned i=0; i<mrMesh.GetNumElements(); i++)
00277 {
00278 mrMesh.GetInverseJacobianForElement(i, jacobian, jacobian_det, inverse_jacobian);
00279
00280 c_vector<double,DIM+1> circumsphere = mrMesh.GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
00281
00282 c_vector<double,DIM>* p_circumcentre = new c_vector<double, DIM>;
00283 for (unsigned j=0; j<DIM; j++)
00284 {
00285 (*p_circumcentre)(j)=circumsphere(j);
00286 }
00287 mVertices.push_back(p_circumcentre);
00288 }
00289 }
00290
00291 template<unsigned DIM>
00292 const VoronoiCell& VoronoiTessellation<DIM>::rGetCell(unsigned index) const
00293 {
00294 #define COVERAGE_IGNORE
00295 assert(DIM==3);
00296 #undef COVERAGE_IGNORE
00297
00298 return mVoronoiCells[index];
00299 }
00300
00301 template<unsigned DIM>
00302 const Face<DIM>& VoronoiTessellation<DIM>::rGetFace(unsigned index) const
00303 {
00304 #define COVERAGE_IGNORE
00305 assert(DIM==2);
00306 #undef COVERAGE_IGNORE
00307
00308 if (!mLocationIndices.empty())
00309 {
00310 if (mLocationIndices.find(index) == mLocationIndices.end())
00311 {
00312 EXCEPTION("Attempting to get a Face corresponding to a ghost node");
00313 }
00314 }
00315
00316 return *(mFaces[index]);
00317 }
00318
00319 template<unsigned DIM>
00320 double VoronoiTessellation<DIM>::GetEdgeLength(unsigned nodeIndex1, unsigned nodeIndex2) const
00321 {
00322 #define COVERAGE_IGNORE
00323 assert(DIM==2);
00324 #undef COVERAGE_IGNORE
00325
00326 if (!mLocationIndices.empty())
00327 {
00328 if ( mLocationIndices.find(nodeIndex1) == mLocationIndices.end()
00329 || mLocationIndices.find(nodeIndex2) == mLocationIndices.end() )
00330 {
00331 EXCEPTION("Attempting to get the tessellation edge between two nodes, at least one of which is a ghost node");
00332 }
00333 }
00334
00335 std::vector< c_vector<double, DIM>* > vertices_1;
00336 for (unsigned i=0; i<mFaces[nodeIndex1]->GetNumVertices(); i++)
00337 {
00338 vertices_1.push_back(&(mFaces[nodeIndex1]->rGetVertex(i)));
00339 }
00340 std::vector< c_vector<double, DIM>* > vertices_2;
00341 for (unsigned i=0; i<mFaces[nodeIndex2]->GetNumVertices(); i++)
00342 {
00343 vertices_2.push_back(&(mFaces[nodeIndex2]->rGetVertex(i)));
00344 }
00345
00346 std::sort(vertices_1.begin(), vertices_1.end());
00347 std::sort(vertices_2.begin(), vertices_2.end());
00348 std::vector< c_vector<double, DIM>* > intersecting_vertices;
00349
00350 set_intersection( vertices_1.begin(), vertices_1.end(),
00351 vertices_2.begin(), vertices_2.end(),
00352 back_inserter(intersecting_vertices) );
00353
00354 #define COVERAGE_IGNORE //Debug code from r3223
00355 if (intersecting_vertices.size() != 2)
00356 {
00357 std::cout << "node 1 = " << nodeIndex1 << " node 2 = " << nodeIndex2 << " \n" << std::flush;
00358 std::cout << "vertices 1 \n" << std::flush;
00359 for (unsigned i=0; i<vertices_1.size(); i++)
00360 {
00361 c_vector<double, DIM> current_vertex = *(vertices_1[i]);
00362 std::cout << current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00363 }
00364 std::cout << "vertices 2 \n" << std::flush;
00365 for (unsigned i=0; i<vertices_2.size(); i++)
00366 {
00367 c_vector<double, DIM> current_vertex = *(vertices_2[i]);
00368 std::cout << current_vertex[0] << " \t" << current_vertex[1] << " \n" << std::flush;
00369 }
00370 std::cout << "size of common vertices = " << intersecting_vertices.size() << " \n" << std::flush;
00371 }
00372 #undef COVERAGE_IGNORE
00373 assert(intersecting_vertices.size()==2);
00374
00375 c_vector<double, DIM> edge_vector = mrMesh.GetVectorFromAtoB( *(intersecting_vertices[0]),
00376 *(intersecting_vertices[1]) );
00377
00378 return norm_2(edge_vector);
00379 }
00380
00381 template<unsigned DIM>
00382 double VoronoiTessellation<DIM>::GetFaceArea(unsigned index) const
00383 {
00384 #define COVERAGE_IGNORE
00385 assert(DIM==2);
00386 #undef COVERAGE_IGNORE
00387
00388 if (!mLocationIndices.empty())
00389 {
00390 if (mLocationIndices.find(index) == mLocationIndices.end())
00391 {
00392 EXCEPTION("Attempting to get the area of a Face corresponding to a ghost node");
00393 }
00394 }
00395
00396 Face<DIM>& face = *(mFaces[index]);
00397 assert(face.GetNumVertices() > 0);
00398
00399 Face<DIM> normalised_face;
00400 std::vector< c_vector<double, DIM> > normalised_vertices;
00401 normalised_vertices.reserve(face.GetNumVertices());
00402
00403 c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00404 normalised_vertices.push_back(vertex);
00405
00406 normalised_face.AddVertex( &(normalised_vertices[0]) );
00407
00408 for (unsigned vertex_index=1; vertex_index<face.GetNumVertices(); vertex_index++)
00409 {
00410 vertex = mrMesh.GetVectorFromAtoB(face.rGetVertex(0), face.rGetVertex(vertex_index));
00411 normalised_vertices.push_back(vertex);
00412 normalised_face.AddVertex( &(normalised_vertices.back()) );
00413 }
00414 normalised_face.OrderVerticesAntiClockwise();
00415
00416 double normalised_face_area = 0;
00417 for (unsigned i=0; i<normalised_face.GetNumVertices(); i++)
00418 {
00419
00420
00421
00422
00423 c_vector<double, DIM> this_vertex = normalised_face.rGetVertex(i);
00424 c_vector<double, DIM> next_vertex = normalised_face.rGetVertex((i+1)%normalised_face.GetNumVertices());
00425
00426 normalised_face_area += 0.5*( this_vertex(0)*next_vertex(1) - this_vertex(1)*next_vertex(0) );
00427 }
00428 return normalised_face_area;
00429 }
00430
00431 template<unsigned DIM>
00432 double VoronoiTessellation<DIM>::GetFacePerimeter(unsigned index) const
00433 {
00434 #define COVERAGE_IGNORE
00435 assert(DIM==2);
00436 #undef COVERAGE_IGNORE
00437
00438 if (!mLocationIndices.empty())
00439 {
00440 if (mLocationIndices.find(index) == mLocationIndices.end())
00441 {
00442 EXCEPTION("Attempting to get the perimeter of a Face corresponding to a ghost node");
00443 }
00444 }
00445
00446 Face<DIM>& face = *(mFaces[index]);
00447 assert(face.GetNumVertices() > 0);
00448
00449 Face<DIM> normalised_face;
00450 std::vector< c_vector<double, DIM> > normalised_vertices;
00451 normalised_vertices.reserve(face.GetNumVertices());
00452
00453 c_vector<double, DIM> vertex = zero_vector<double>(DIM);
00454 normalised_vertices.push_back(vertex);
00455
00456 normalised_face.AddVertex( &(normalised_vertices[0]) );
00457
00458 for (unsigned vertex_index=1; vertex_index<face.GetNumVertices(); vertex_index++)
00459 {
00460 vertex = mrMesh.GetVectorFromAtoB(face.rGetVertex(0), face.rGetVertex(vertex_index));
00461 normalised_vertices.push_back(vertex);
00462 normalised_face.AddVertex( &(normalised_vertices.back()) );
00463 }
00464 normalised_face.OrderVerticesAntiClockwise();
00465
00466 double normalised_face_perimeter = 0;
00467 for (unsigned i=0; i<normalised_face.GetNumVertices(); i++)
00468 {
00469 c_vector<double, DIM> this_vertex = normalised_face.rGetVertex(i);
00470 c_vector<double, DIM> next_vertex = normalised_face.rGetVertex((i+1)%normalised_face.GetNumVertices());
00471
00472 normalised_face_perimeter += norm_2(this_vertex - next_vertex);
00473 }
00474 return normalised_face_perimeter;
00475 }
00476
00477 template<unsigned DIM>
00478 unsigned VoronoiTessellation<DIM>::GetNumVertices() const
00479 {
00480 return mVertices.size();
00481 }
00482
00483 template<unsigned DIM>
00484 unsigned VoronoiTessellation<DIM>::GetNumFaces() const
00485 {
00487 return mFaces.size();
00488 }
00489
00490 template<unsigned DIM>
00491 unsigned VoronoiTessellation<DIM>::GetNumCells()
00492 {
00493 assert(DIM==3);
00494 return mVoronoiCells.size();
00495 }
00496
00497 template<unsigned DIM>
00498 c_vector<double,DIM>* VoronoiTessellation<DIM>::GetVertex(unsigned index)
00499 {
00500 assert(index<mVertices.size());
00501 return mVertices[index];
00502 }
00503
00504
00506
00508
00509
00510 template class VoronoiTessellation<1>;
00511 template class VoronoiTessellation<2>;
00512 template class VoronoiTessellation<3>;