TrianglesMeshReader.hpp

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 #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         // Only linear and quadratic elements
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; // Initially assume that nodes are not numbered from zero
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         // In the first two cases there's no file, all the nodes are set as faces
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;//In case ELEMENT_DIM is erroneously instatiated to zero
00263             assert(element_dim != 0); //Covered in earlier exception, but needed in loop guard here.
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         // Nodes definition
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         // Elements definition
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         // Faces/edges definition
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             //There is no file, data will be generated instead of read
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         // get the next line to see if it is indexed from zero or not                
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         //close, reopen, skip header
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             // if mNumFaceAttributes=1 then loop over and set mNumFaces to be
00473             // the number of faces which are marked as boundary faces
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                 // close the file, reopen, and skip the header again
00493                 mFacesFile.close();
00494                 mFacesFile.clear(); // Older versions of gcc don't explicitly reset "fail" and "eof" flags in std::ifstream after calling close()
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             // Get rid of any comment
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_

Generated on Wed Mar 18 12:51:52 2009 for Chaste by  doxygen 1.5.5