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
00032
00034
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
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
00078 Face<2> *p_face = new Face<2>;
00079 mFaces.push_back(p_face);
00080 }
00081
00082
00083
00084
00085
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
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
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
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
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
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
00187
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
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
00205 std::sort(vertices.begin(), vertices.end());
00206
00207
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
00217 mFaces.push_back(p_face);
00218
00219
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
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
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
00425
00426
00427 template class VoronoiTessellation<1>;
00428 template class VoronoiTessellation<2>;
00429 template class VoronoiTessellation<3>;