00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00062
00063
00064 GLC_World* GLC_StlToWorld::CreateWorldFromStl(QFile &file)
00065 {
00066 clear();
00067 m_FileName= file.fileName();
00069
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
00081 m_pWorld= new GLC_World;
00082
00083
00084 int currentQuantumValue= 0;
00085 int previousQuantumValue= 0;
00086 int numberOfLine= 0;
00087
00088
00089 m_StlStream.setDevice(&file);
00090
00091
00092 QString lineBuff;
00093
00095
00097 while (!m_StlStream.atEnd())
00098 {
00099 ++numberOfLine;
00100 m_StlStream.readLine();
00101 }
00102
00104
00106 m_StlStream.resetStatus();
00107 m_StlStream.seek(0);
00109
00111
00112 emit currentQuantum(currentQuantumValue);
00113 m_CurrentLineNumber= 0;
00114
00115
00116
00117 ++m_CurrentLineNumber;
00118 lineBuff= m_StlStream.readLine();
00119 lineBuff= lineBuff.trimmed().toLower();
00120 if (!lineBuff.startsWith("solid"))
00121 {
00122
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
00140 lineBuff.remove(0, 5);
00141 lineBuff= lineBuff.trimmed();
00142 m_pCurrentMesh= new GLC_Mesh();
00143 m_pCurrentMesh->setName(lineBuff);
00144
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
00165
00166
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
00182 void GLC_StlToWorld::scanFacet()
00183 {
00185 ++m_CurrentLineNumber;
00186 QString lineBuff(m_StlStream.readLine());
00187 lineBuff= lineBuff.trimmed().toLower();
00188
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
00205 if (lineBuff.startsWith("solid"))
00206 {
00207
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
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);
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
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
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);
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
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
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
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
00354 void GLC_StlToWorld::LoadBinariStl(QFile &file)
00355 {
00356
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
00366 int SkipedData= stlBinFile.skipRawData(80);
00367
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
00377 quint32 numberOfFacet= 0;
00378 stlBinFile >> numberOfFacet;
00379
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
00391 float nx, ny, nz;
00392 stlBinFile >> nx >> ny >> nz;
00393
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
00404 for (int j= 0; j < 3; ++j)
00405 {
00406 float x, y, z;
00407 stlBinFile >> x >> y >> z;
00408
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
00436 stlBinFile.skipRawData(2);
00437
00438 }
00439 }
00440