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 _TRIANGLESMESHREADER_HPP_
00031 #define _TRIANGLESMESHREADER_HPP_
00032
00033 #include <vector>
00034 #include <string>
00035 #include <fstream>
00036 #include <cassert>
00037 #include "AbstractMeshReader.hpp"
00038
00039 const static char* NODES_FILE_EXTENSION = ".node";
00040 const static char* ELEMENTS_FILE_EXTENSION = ".ele";
00041 const static char* FACES_FILE_EXTENSION = ".face";
00042 const static char* EDGES_FILE_EXTENSION = ".edge";
00043
00044 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00045 class TrianglesMeshReader : public AbstractMeshReader<ELEMENT_DIM,SPACE_DIM>
00046 {
00047 private:
00048
00049 bool mIndexFromZero;
00051 std::string mFilesBaseName;
00052
00053 std::ifstream mNodesFile;
00054 std::ifstream mElementsFile;
00055 std::ifstream mFacesFile;
00056
00057 unsigned mNumNodes;
00058 unsigned mNumElements;
00059 unsigned mNumFaces;
00060
00061 unsigned mNodesRead;
00062 unsigned mElementsRead;
00063 unsigned mFacesRead;
00064 unsigned mBoundaryFacesRead;
00065
00066 unsigned mNumNodeAttributes;
00067 unsigned mMaxNodeBdyMarker;
00068 unsigned mNumElementNodes;
00069 unsigned mNumElementAttributes;
00070 unsigned mNumFaceAttributes;
00072 unsigned mOrderOfElements;
00073 unsigned mNodesPerElement;
00074
00075 public:
00076 TrianglesMeshReader(std::string pathBaseName, unsigned orderOfElements=1):
00077 mFilesBaseName(pathBaseName),
00078 mNumNodes(0),
00079 mNumElements(0),
00080 mNumFaces(0),
00081 mNodesRead(0),
00082 mElementsRead(0),
00083 mFacesRead(0),
00084 mBoundaryFacesRead(0),
00085 mNumElementAttributes(0),
00086 mNumFaceAttributes(0),
00087 mOrderOfElements(orderOfElements)
00088 {
00089
00090 assert(orderOfElements==1 || orderOfElements==2);
00091 if(mOrderOfElements==1)
00092 {
00093 mNodesPerElement = ELEMENT_DIM+1;
00094 }
00095 else
00096 {
00097 #define COVERAGE_IGNORE
00098 assert(SPACE_DIM==ELEMENT_DIM);
00099 #undef COVERAGE_IGNORE
00100 mNodesPerElement = (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2;
00101 }
00102
00103 mIndexFromZero = false;
00104
00105
00106 OpenFiles();
00107
00108 ReadHeaders();
00109
00110 }
00111
00113 unsigned GetNumElements() const
00114 {
00115 return mNumElements;
00116 }
00117
00119 unsigned GetNumNodes() const
00120 {
00121 return mNumNodes;
00122 }
00123
00125 unsigned GetNumFaces() const
00126 {
00127 return mNumFaces;
00128 }
00129
00131 unsigned GetNumEdges() const
00132 {
00133 return mNumFaces;
00134 }
00135
00137 unsigned GetNumElementAttributes() const
00138 {
00139 return mNumElementAttributes;
00140 }
00141
00143 unsigned GetNumFaceAttributes() const
00144 {
00145 return mNumFaceAttributes;
00146 }
00147
00149 void Reset()
00150 {
00151 CloseFiles();
00152 OpenFiles();
00153 ReadHeaders();
00154
00155 mNodesRead=0;
00156 mElementsRead=0;
00157 mFacesRead=0;
00158 mBoundaryFacesRead=0;
00159 }
00160
00161
00163 std::vector<double> GetNextNode()
00164 {
00165 std::vector<double> ret_coords;
00166
00167 std::string buffer;
00168 GetNextLineFromStream(mNodesFile, buffer);
00169
00170 std::stringstream buffer_stream(buffer);
00171
00172 unsigned index;
00173 buffer_stream >> index;
00174
00175 unsigned offset = mIndexFromZero ? 0 : 1;
00176 if(index != mNodesRead+offset)
00177 {
00178 std::stringstream error;
00179 error << "Data for node " << mNodesRead << " missing";
00180 EXCEPTION(error.str());
00181 }
00182
00183 double coord;
00184
00185 for (unsigned i = 0; i < SPACE_DIM; i++)
00186 {
00187 buffer_stream >> coord;
00188 ret_coords.push_back(coord);
00189 }
00190
00191 mNodesRead++;
00192
00193 return ret_coords;
00194 }
00195
00197 ElementData GetNextElementData()
00198 {
00199 ElementData element_data;
00200
00201 std::string buffer;
00202 GetNextLineFromStream(mElementsFile, buffer);
00203
00204 std::stringstream buffer_stream(buffer);
00205
00206 unsigned element_index;
00207 buffer_stream >> element_index;
00208
00209 unsigned offset = mIndexFromZero ? 0 : 1;
00210 if(element_index != mElementsRead+offset)
00211 {
00212 std::stringstream error;
00213 error << "Data for element " << mElementsRead << " missing";
00214 EXCEPTION(error.str());
00215 }
00216
00217 unsigned node_index;
00218 for (unsigned i=0; i<mNodesPerElement; i++)
00219 {
00220 buffer_stream >> node_index;
00221 element_data.NodeIndices.push_back(node_index - offset);
00222 }
00223
00224 if(mNumElementAttributes>0)
00225 {
00226 assert(mNumElementAttributes==1);
00227
00228 unsigned attribute_value;
00229 buffer_stream >> attribute_value;
00230 element_data.AttributeValue = attribute_value;
00231 }
00232 else
00233 {
00234 element_data.AttributeValue = 0;
00235 }
00236
00237
00238 mElementsRead++;
00239
00240 return element_data;
00241 }
00242
00244 ElementData GetNextFaceData()
00245 {
00246 ElementData face_data;
00247 std::vector<unsigned> ret_indices;
00248
00249
00250 if (SPACE_DIM == 1)
00251 {
00252 ret_indices.push_back(mBoundaryFacesRead);
00253 }
00254 else if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00255 {
00256 ret_indices.push_back(mBoundaryFacesRead);
00257 }
00258 else
00259 {
00260 unsigned offset = mIndexFromZero ? 0 : 1;
00261
00262 unsigned element_dim=ELEMENT_DIM;
00263 assert(element_dim != 0);
00264 do
00265 {
00266 ret_indices.clear();
00267
00268 std::string buffer;
00269 GetNextLineFromStream(mFacesFile, buffer);
00270
00271 std::stringstream buffer_stream(buffer);
00272
00273 unsigned face_index;
00274 buffer_stream >> face_index;
00275
00276 if(face_index != mFacesRead+offset)
00277 {
00278 std::stringstream error;
00279 error << "Data for face " << mFacesRead << " missing";
00280 EXCEPTION(error.str());
00281 }
00282
00283 unsigned node_index;
00284 for (unsigned i = 0; i<element_dim; i++)
00285 {
00286 buffer_stream >> node_index;
00287 ret_indices.push_back(node_index-offset);
00288 }
00289
00290 if(mNumFaceAttributes>0)
00291 {
00292 assert(mNumFaceAttributes==1);
00293
00294 unsigned attribute_value;
00295 buffer_stream >> attribute_value;
00296 face_data.AttributeValue = attribute_value;
00297 }
00298 else
00299 {
00300 face_data.AttributeValue = 0u;
00301 }
00302
00303 mFacesRead++;
00304 }
00305 while((mNumFaceAttributes==1) && (face_data.AttributeValue==0));
00306 }
00307
00308 mBoundaryFacesRead++;
00309 face_data.NodeIndices = ret_indices;
00310 return face_data;
00311 }
00312
00314 ElementData GetNextEdgeData()
00315 {
00316 return GetNextFaceData();
00317 }
00318
00319
00320 private:
00321
00322 void OpenFiles()
00323 {
00324 OpenNodeFile();
00325 OpenElementsFile();
00326 OpenFacesFile();
00327 }
00328
00329 void OpenNodeFile()
00330 {
00331
00332 std::string file_name = mFilesBaseName + NODES_FILE_EXTENSION;
00333 mNodesFile.open(file_name.c_str());
00334 if (!mNodesFile.is_open())
00335 {
00336 EXCEPTION("Could not open data file: "+file_name);
00337 }
00338 }
00339
00340 void OpenElementsFile()
00341 {
00342
00343 std::string file_name;
00344 if (ELEMENT_DIM == SPACE_DIM)
00345 {
00346 file_name = mFilesBaseName + ELEMENTS_FILE_EXTENSION;
00347 }
00348 else
00349 {
00350 if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00351 {
00352 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00353 }
00354 else if (SPACE_DIM == 3 && ELEMENT_DIM == 2)
00355 {
00356 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00357 }
00358 else
00359 {
00360 EXCEPTION("Can't have a zero-dimensional mesh in a one-dimensional space or a one-dimensional mesh in a three-dimensional space");
00361 }
00362 }
00363
00364 mElementsFile.open(file_name.c_str());
00365 if (!mElementsFile.is_open())
00366 {
00367 EXCEPTION("Could not open data file: "+file_name);
00368 }
00369 }
00370
00371 void OpenFacesFile()
00372 {
00373
00374 std::string file_name;
00375 if (SPACE_DIM == 3)
00376 {
00377 if (SPACE_DIM == ELEMENT_DIM)
00378 {
00379 file_name = mFilesBaseName + FACES_FILE_EXTENSION;
00380 }
00381 else
00382 {
00383 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00384 }
00385 }
00386 else if (SPACE_DIM == 2)
00387 {
00388 file_name = mFilesBaseName + EDGES_FILE_EXTENSION;
00389 }
00390 else if (SPACE_DIM == 1)
00391 {
00392
00393 return;
00394 }
00395
00396 mFacesFile.open(file_name.c_str());
00397 if (!mFacesFile.is_open())
00398 {
00399 EXCEPTION("Could not open data file: "+file_name);
00400 }
00401 }
00402
00403 void ReadHeaders()
00404 {
00405 std::string buffer;
00406
00407 GetNextLineFromStream(mNodesFile, buffer);
00408 std::stringstream buffer_stream(buffer);
00409 unsigned dimension;
00410 buffer_stream >> mNumNodes >> dimension >> mNumNodeAttributes >> mMaxNodeBdyMarker;
00411 if (SPACE_DIM != dimension)
00412 {
00413 EXCEPTION("SPACE_DIM != dimension read from file ");
00414 }
00415
00416
00417 GetNextLineFromStream(mNodesFile, buffer);
00418 std::stringstream buffer_stream_ii(buffer);
00419
00420 unsigned first_index;
00421 buffer_stream_ii >> first_index;
00422 assert(first_index == 0 || first_index == 1);
00423 mIndexFromZero = (first_index == 0);
00424
00425
00426 mNodesFile.close();
00427 OpenNodeFile();
00428 GetNextLineFromStream(mNodesFile, buffer);
00429
00430
00432 GetNextLineFromStream(mElementsFile, buffer);
00433 std::stringstream buffer_stream2(buffer);
00434
00435 if (ELEMENT_DIM == SPACE_DIM)
00436 {
00437 buffer_stream2 >> mNumElements >> mNumElementNodes >> mNumElementAttributes;
00438
00439 if( mNumElementNodes != mNodesPerElement )
00440 {
00441 std::stringstream error;
00442 error << "Number of nodes per elem, " << mNumElementNodes << ", does not match "
00443 << "expected number, " << mNodesPerElement << " (which is calculated given "
00444 << "the order of elements chosen, " << mOrderOfElements << " (1=linear, 2=quadratics)";
00445 EXCEPTION(error.str());
00446 }
00447 }
00448 else
00449 {
00450 buffer_stream2 >> mNumElements >> mNumFaceAttributes;
00451
00452 mNodesPerElement = ELEMENT_DIM+1;
00453 }
00454
00455
00456 if (SPACE_DIM == 1)
00457 {
00458 mNumFaces = mNumNodes;
00459 }
00460 else if (SPACE_DIM == 2 && ELEMENT_DIM == 1)
00461 {
00462 mNumFaces = mNumNodes;
00463 }
00464 else
00465 {
00466 GetNextLineFromStream(mFacesFile, buffer);
00467 std::stringstream buffer_stream3(buffer);
00468
00469 buffer_stream3 >> mNumFaces >> mNumFaceAttributes;
00470 assert(mNumFaceAttributes==0 || mNumFaceAttributes==1);
00471
00472
00473
00474 if((mNumFaceAttributes==1) && (SPACE_DIM!=1))
00475 {
00476 unsigned num_boundary_faces = 0;
00477 bool end_of_file=false;
00478 while(!end_of_file)
00479 {
00480 try
00481 {
00482 GetNextFaceData();
00483 num_boundary_faces++;
00484 }
00485 catch(Exception& e)
00486 {
00487 end_of_file = true;
00488 }
00489 }
00490 mNumFaces = num_boundary_faces;
00491
00492
00493 mFacesFile.close();
00494 mFacesFile.clear();
00495 OpenFacesFile();
00496 GetNextLineFromStream(mFacesFile, buffer);
00497 mFacesRead=0;
00498 mBoundaryFacesRead=0;
00499 }
00500 }
00501
00502 }
00503
00504 void CloseFiles()
00505 {
00506 mNodesFile.close();
00507 mElementsFile.close();
00508 mFacesFile.close();
00509 }
00510
00511 void GetNextLineFromStream(std::ifstream& fileStream, std::string& rawLine)
00512 {
00513 bool line_is_blank;
00514
00515 do
00516 {
00517 getline(fileStream, rawLine);
00518
00519 if (fileStream.eof())
00520 {
00522 EXCEPTION("File contains incomplete data");
00523 }
00524
00525
00526 rawLine = rawLine.substr(0,rawLine.find('#',0));
00527
00528 line_is_blank = (rawLine.find_first_not_of(" \t",0) == std::string::npos);
00529 }
00530 while (line_is_blank);
00531 }
00532
00533 std::string GetMeshFileBaseName()
00534 {
00535 return mFilesBaseName;
00536 }
00537 };
00538
00539 #endif //_TRIANGLESMESHREADER_HPP_