glc_stltoworld.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  Version 2.0.0 Beta 1, packaged on April 2010.
00006 
00007  http://glc-lib.sourceforge.net
00008 
00009  GLC-lib is free software; you can redistribute it and/or modify
00010  it under the terms of the GNU General Public License as published by
00011  the Free Software Foundation; either version 2 of the License, or
00012  (at your option) any later version.
00013 
00014  GLC-lib is distributed in the hope that it will be useful,
00015  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  GNU General Public License for more details.
00018 
00019  You should have received a copy of the GNU General Public License
00020  along with GLC-lib; if not, write to the Free Software
00021  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 *****************************************************************************/
00024 
00026 
00027 #include "glc_stltoworld.h"
00028 #include "../sceneGraph/glc_world.h"
00029 #include "../glc_fileformatexception.h"
00030 #include "../sceneGraph/glc_structreference.h"
00031 #include "../sceneGraph/glc_structinstance.h"
00032 #include "../sceneGraph/glc_structoccurence.h"
00033 
00034 #include <QTextStream>
00035 #include <QFileInfo>
00036 #include <QGLContext>
00037 #include <QDataStream>
00038 
00039 GLC_StlToWorld::GLC_StlToWorld()
00040 : QObject()
00041 , m_pWorld(NULL)
00042 , m_FileName()
00043 , m_CurrentLineNumber(0)
00044 , m_StlStream()
00045 , m_pCurrentMesh(NULL)
00046 , m_CurrentFace()
00047 , m_VertexBulk()
00048 , m_NormalBulk()
00049 , m_CurrentIndex(0)
00050 {
00051 
00052 }
00053 
00054 GLC_StlToWorld::~GLC_StlToWorld()
00055 {
00056         clear();
00057 }
00058 
00060 // Set Functions
00062 
00063 // Create an GLC_World from an input STL File
00064 GLC_World* GLC_StlToWorld::CreateWorldFromStl(QFile &file)
00065 {
00066         clear();
00067         m_FileName= file.fileName();
00069         // Test if the file exist and can be opened
00071         if (!file.open(QIODevice::ReadOnly))
00072         {
00073                 QString message(QString("GLC_StlToWorld::CreateWorldFromStl File ") + m_FileName + QString(" doesn't exist"));
00074                 qDebug() << message;
00075                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00076                 throw(fileFormatException);
00077         }
00079         // Init member
00081         m_pWorld= new GLC_World;
00082 
00083         // Create Working variables
00084         int currentQuantumValue= 0;
00085         int previousQuantumValue= 0;
00086         int numberOfLine= 0;
00087 
00088         // Attach the stream to the file
00089         m_StlStream.setDevice(&file);
00090 
00091         // QString buffer
00092         QString lineBuff;
00093 
00095         // Count the number of lines of the STL file
00097         while (!m_StlStream.atEnd())
00098         {
00099                 ++numberOfLine;
00100                 m_StlStream.readLine();
00101         }
00102 
00104         // Reset the stream
00106         m_StlStream.resetStatus();
00107         m_StlStream.seek(0);
00109         // Read Buffer and create the world
00111 
00112         emit currentQuantum(currentQuantumValue);
00113         m_CurrentLineNumber= 0;
00114         // Search Object section in the STL
00115 
00116         // Test if the STL File is ASCII or Binary
00117         ++m_CurrentLineNumber;
00118         lineBuff= m_StlStream.readLine();
00119         lineBuff= lineBuff.trimmed().toLower();
00120         if (!lineBuff.startsWith("solid"))
00121         {
00122                 // The STL File is not ASCII trying to load Binary STL File
00123                 m_pCurrentMesh= new GLC_Mesh();
00124                 file.reset();
00125                 LoadBinariStl(file);
00126                 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00127                 m_CurrentFace.clear();
00128                 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00129                 m_VertexBulk.clear();
00130                 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00131                 m_NormalBulk.clear();
00132                 m_pCurrentMesh->finish();
00133                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00134                 m_pCurrentMesh= NULL;
00135                 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00136         }
00137         else
00138         {
00139                 // The STL File is ASCII
00140                 lineBuff.remove(0, 5);
00141                 lineBuff= lineBuff.trimmed();
00142                 m_pCurrentMesh= new GLC_Mesh();
00143                 m_pCurrentMesh->setName(lineBuff);
00144                 // Read the mesh facet
00145                 while (!m_StlStream.atEnd())
00146                 {
00147                         scanFacet();
00148 
00149                         currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
00150                         if (currentQuantumValue > previousQuantumValue)
00151                         {
00152                                 emit currentQuantum(currentQuantumValue);
00153                         }
00154                         previousQuantumValue= currentQuantumValue;
00155                 }
00156         }
00157         file.close();
00158 
00159         return m_pWorld;
00160 }
00161 
00163 // Private services Functions
00165 
00166 // clear stlToWorld allocate memmory and reset member
00167 void GLC_StlToWorld::clear()
00168 {
00169         if (NULL != m_pCurrentMesh)
00170         {
00171                 delete m_pCurrentMesh;
00172                 m_pCurrentMesh= NULL;
00173         }
00174         m_pWorld= NULL;
00175         m_FileName.clear();
00176         m_CurrentLineNumber= 0;
00177         m_pCurrentMesh= NULL;
00178         m_CurrentFace.clear();
00179 }
00180 
00181 // Scan a line previously extracted from STL file
00182 void GLC_StlToWorld::scanFacet()
00183 {
00185         ++m_CurrentLineNumber;
00186         QString lineBuff(m_StlStream.readLine());
00187         lineBuff= lineBuff.trimmed().toLower();
00188         // Test if this is the end of current solid
00189         if (lineBuff.startsWith("endsolid") || lineBuff.startsWith("end solid"))
00190         {
00191                 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00192                 m_CurrentFace.clear();
00193                 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00194                 m_VertexBulk.clear();
00195                 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00196                 m_NormalBulk.clear();
00197 
00198                 m_pCurrentMesh->finish();
00199                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00200                 m_pCurrentMesh= NULL;
00201                 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00202                 return;
00203         }
00204         // Test if this is the start of new solid
00205         if (lineBuff.startsWith("solid"))
00206         {
00207                 // The STL File is ASCII
00208                 lineBuff.remove(0, 5);
00209                 lineBuff= lineBuff.trimmed();
00210                 m_pCurrentMesh= new GLC_Mesh();
00211                 m_pCurrentMesh->setName(lineBuff);
00212                 return;
00213         }
00214 
00216         // lineBuff Must begin with "facet normal"
00217         if (!lineBuff.startsWith("facet normal"))
00218         {
00219                 QString message= "GLC_StlToWorld::scanFacet : \"facet normal\" not found!";
00220                 message.append("\nAt line : ");
00221                 message.append(QString::number(m_CurrentLineNumber));
00222                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00223                 clear();
00224                 qDebug() << message;
00225                 throw(fileFormatException);
00226         }
00227         lineBuff.remove(0,12); // Remove first 12 chars
00228         lineBuff= lineBuff.trimmed().toLower();
00229         GLC_Vector3df cur3dVect= extract3dVect(lineBuff);
00230         for (int i= 0; i < 3; ++i)
00231         {
00232                 m_NormalBulk.append(cur3dVect.X());
00233                 m_NormalBulk.append(cur3dVect.Y());
00234                 m_NormalBulk.append(cur3dVect.Z());
00235         }
00236 
00238         ++m_CurrentLineNumber;
00239         lineBuff= m_StlStream.readLine();
00240         lineBuff= lineBuff.trimmed().toLower();
00241         // lineBuff Must begin with "outer loop"
00242         if (!lineBuff.startsWith("outer loop"))
00243         {
00244                 QString message= "GLC_StlToWorld::scanFacet : \"outer loop\" not found!";
00245                 message.append("\nAt line : ");
00246                 message.append(QString::number(m_CurrentLineNumber));
00247                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00248                 clear();
00249                 qDebug() << message;
00250                 throw(fileFormatException);
00251         }
00252 
00254 
00255         for (int i= 0; i < 3; ++i)
00256         {
00257                 ++m_CurrentLineNumber;
00258                 lineBuff= m_StlStream.readLine();
00259                 lineBuff= lineBuff.trimmed().toLower();
00260                 // lineBuff Must begin with "vertex"
00261                 if (!lineBuff.startsWith("vertex"))
00262                 {
00263                         QString message= "GLC_StlToWorld::scanFacet : \"vertex\" not found!";
00264                         message.append("\nAt line : ");
00265                         message.append(QString::number(m_CurrentLineNumber));
00266                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00267                         clear();
00268                         throw(fileFormatException);
00269                 }
00270                 lineBuff.remove(0,6); // Remove first 6 chars
00271                 lineBuff= lineBuff.trimmed();
00272 
00273                 cur3dVect= extract3dVect(lineBuff);
00274                 m_VertexBulk.append(cur3dVect.X());
00275                 m_VertexBulk.append(cur3dVect.Y());
00276                 m_VertexBulk.append(cur3dVect.Z());
00277 
00278                 m_CurrentFace.append(m_CurrentIndex);
00279                 ++m_CurrentIndex;
00280         }
00281 
00283         ++m_CurrentLineNumber;
00284         lineBuff= m_StlStream.readLine();
00285         lineBuff= lineBuff.trimmed().toLower();
00286         // lineBuff Must begin with "endloop"
00287         if (!lineBuff.startsWith("endloop"))
00288         {
00289                 QString message= "GLC_StlToWorld::scanFacet : \"endloop\" not found!";
00290                 message.append("\nAt line : ");
00291                 message.append(QString::number(m_CurrentLineNumber));
00292                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00293                 clear();
00294                 qDebug() << message;
00295                 throw(fileFormatException);
00296         }
00297 
00299         ++m_CurrentLineNumber;
00300         lineBuff= m_StlStream.readLine();
00301         lineBuff= lineBuff.trimmed().toLower();
00302         // lineBuff Must begin with "endfacet"
00303         if (!lineBuff.startsWith("endfacet"))
00304         {
00305                 QString message= "GLC_StlToWorld::scanFacet : \"endfacet\" not found!";
00306                 message.append("\nAt line : ");
00307                 message.append(QString::number(m_CurrentLineNumber));
00308                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00309                 clear();
00310                 qDebug() << message;
00311                 throw(fileFormatException);
00312         }
00313 
00314 }
00315 
00316 // Extract a Vector from a string
00317 GLC_Vector3df GLC_StlToWorld::extract3dVect(QString &line)
00318 {
00319         float x=0.0f;
00320         float y=0.0f;
00321         float z=0.0f;
00322 
00323         GLC_Vector3df vectResult;
00324         QTextStream stringVecteur(&line);
00325 
00326         QString xString, yString, zString;
00327 
00328         if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00329         {
00330                 bool xOk, yOk, zOk;
00331                 x= xString.toFloat(&xOk);
00332                 y= yString.toFloat(&yOk);
00333                 z= zString.toFloat(&zOk);
00334                 if (!(xOk && yOk && zOk))
00335                 {
00336                         QString message= "GLC_StlToWorld::extract3dVect : failed to convert vector component to float";
00337                         message.append("\nAt ligne : ");
00338                         message.append(QString::number(m_CurrentLineNumber));
00339                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00340                         clear();
00341                         qDebug() << message;
00342                         throw(fileFormatException);
00343                 }
00344                 else
00345                 {
00346                         vectResult.setVect(x, y, z);
00347                 }
00348         }
00349 
00350         return vectResult;
00351 
00352 }
00353 // Load Binarie STL File
00354 void GLC_StlToWorld::LoadBinariStl(QFile &file)
00355 {
00356         // Create Working variables
00357         int currentQuantumValue= 0;
00358         int previousQuantumValue= 0;
00359 
00360         QDataStream stlBinFile(&file);
00361         stlBinFile.setVersion(QDataStream::Qt_4_6);
00362         stlBinFile.setFloatingPointPrecision(QDataStream::SinglePrecision);
00363         stlBinFile.setByteOrder(QDataStream::LittleEndian);
00364 
00365         // Skip 80 Bytes STL header
00366         int SkipedData= stlBinFile.skipRawData(80);
00367         // Check if an error occur
00368         if (-1 == SkipedData)
00369         {
00370                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to skip Header of binary STL";
00371                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00372                 clear();
00373                 qDebug() << message;
00374                 throw(fileFormatException);
00375         }
00376         // Read the number of facet
00377         quint32 numberOfFacet= 0;
00378         stlBinFile >> numberOfFacet;
00379         // Check if an error occur
00380         if (QDataStream::Ok != stlBinFile.status())
00381         {
00382                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the number of facets of binary STL";
00383                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00384                 clear();
00385                 qDebug() << message;
00386                 throw(fileFormatException);
00387         }
00388         for (quint32 i= 0; i < numberOfFacet; ++i)
00389         {
00390                 // Extract the facet normal
00391                 float nx, ny, nz;
00392                 stlBinFile >> nx >> ny >> nz;
00393                 // Check if an error occur
00394                 if (QDataStream::Ok != stlBinFile.status())
00395                 {
00396                         QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Normal of binary STL";
00397                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00398                         clear();
00399                         qDebug() << message;
00400                         throw(fileFormatException);
00401                 }
00402 
00403                 // Extract the 3 Vertexs
00404                 for (int j= 0; j < 3; ++j)
00405                 {
00406                         float x, y, z;
00407                         stlBinFile >> x >> y >> z;
00408                         // Check if an error occur
00409                         if (QDataStream::Ok != stlBinFile.status())
00410                         {
00411                                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Vertex of binary STL";
00412                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00413                                 clear();
00414                                 qDebug() << message;
00415                                 throw(fileFormatException);
00416                         }
00417                         m_VertexBulk.append(x);
00418                         m_VertexBulk.append(y);
00419                         m_VertexBulk.append(z);
00420 
00421                         m_NormalBulk.append(nx);
00422                         m_NormalBulk.append(ny);
00423                         m_NormalBulk.append(nz);
00424 
00425                         m_CurrentFace.append(m_CurrentIndex);
00426                         ++m_CurrentIndex;
00427                 }
00428                 currentQuantumValue = static_cast<int>((static_cast<double>(i + 1) / numberOfFacet) * 100);
00429                 if (currentQuantumValue > previousQuantumValue)
00430                 {
00431                         emit currentQuantum(currentQuantumValue);
00432                 }
00433                 previousQuantumValue= currentQuantumValue;
00434 
00435                 // Skip 2 fill-bytes not needed !!!!
00436                 stlBinFile.skipRawData(2);
00437 
00438         }
00439 }
00440 

SourceForge.net Logo

©2005 Laurent Ribon