00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00024
00025 #include "glc_stltoworld.h"
00026 #include "../sceneGraph/glc_world.h"
00027 #include "../glc_fileformatexception.h"
00028 #include "../sceneGraph/glc_structreference.h"
00029 #include "../sceneGraph/glc_structinstance.h"
00030 #include "../sceneGraph/glc_structoccurence.h"
00031
00032 #include <QTextStream>
00033 #include <QFileInfo>
00034 #include <QGLContext>
00035 #include <QDataStream>
00036
00037 GLC_StlToWorld::GLC_StlToWorld()
00038 : QObject()
00039 , m_pWorld(NULL)
00040 , m_FileName()
00041 , m_CurrentLineNumber(0)
00042 , m_StlStream()
00043 , m_pCurrentMesh(NULL)
00044 , m_CurrentFace()
00045 , m_VertexBulk()
00046 , m_NormalBulk()
00047 , m_CurrentIndex(0)
00048 {
00049
00050 }
00051
00052 GLC_StlToWorld::~GLC_StlToWorld()
00053 {
00054 clear();
00055 }
00056
00058
00060
00061
00062 GLC_World* GLC_StlToWorld::CreateWorldFromStl(QFile &file)
00063 {
00064 clear();
00065 m_FileName= file.fileName();
00067
00069 if (!file.open(QIODevice::ReadOnly))
00070 {
00071 QString message(QString("GLC_StlToWorld::CreateWorldFromStl File ") + m_FileName + QString(" doesn't exist"));
00072 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00073 throw(fileFormatException);
00074 }
00076
00078 m_pWorld= new GLC_World;
00079
00080
00081 int currentQuantumValue= 0;
00082 int previousQuantumValue= 0;
00083 int numberOfLine= 0;
00084
00085
00086 m_StlStream.setDevice(&file);
00087
00088
00089 QString lineBuff;
00090
00092
00094 while (!m_StlStream.atEnd())
00095 {
00096 ++numberOfLine;
00097 m_StlStream.readLine();
00098 }
00099
00101
00103 m_StlStream.resetStatus();
00104 m_StlStream.seek(0);
00106
00108
00109 emit currentQuantum(currentQuantumValue);
00110 m_CurrentLineNumber= 0;
00111
00112
00113
00114 ++m_CurrentLineNumber;
00115 lineBuff= m_StlStream.readLine();
00116 lineBuff= lineBuff.trimmed().toLower();
00117 if (!lineBuff.startsWith("solid"))
00118 {
00119
00120 m_pCurrentMesh= new GLC_Mesh();
00121 file.reset();
00122 LoadBinariStl(file);
00123 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00124 m_CurrentFace.clear();
00125 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00126 m_VertexBulk.clear();
00127 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00128 m_NormalBulk.clear();
00129 m_pCurrentMesh->finish();
00130 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00131 m_pCurrentMesh= NULL;
00132 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00133 }
00134 else
00135 {
00136
00137 lineBuff.remove(0, 5);
00138 lineBuff= lineBuff.trimmed();
00139 m_pCurrentMesh= new GLC_Mesh();
00140 m_pCurrentMesh->setName(lineBuff);
00141
00142 while (!m_StlStream.atEnd())
00143 {
00144 scanFacet();
00145
00146 currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
00147 if (currentQuantumValue > previousQuantumValue)
00148 {
00149 emit currentQuantum(currentQuantumValue);
00150 }
00151 previousQuantumValue= currentQuantumValue;
00152 }
00153 }
00154 file.close();
00155
00156 return m_pWorld;
00157 }
00158
00160
00162
00163
00164 void GLC_StlToWorld::clear()
00165 {
00166 if (NULL != m_pCurrentMesh)
00167 {
00168 delete m_pCurrentMesh;
00169 m_pCurrentMesh= NULL;
00170 }
00171 m_pWorld= NULL;
00172 m_FileName.clear();
00173 m_CurrentLineNumber= 0;
00174 m_pCurrentMesh= NULL;
00175 m_CurrentFace.clear();
00176 }
00177
00178
00179 void GLC_StlToWorld::scanFacet()
00180 {
00182 ++m_CurrentLineNumber;
00183 QString lineBuff(m_StlStream.readLine());
00184 lineBuff= lineBuff.trimmed().toLower();
00185
00186 if (lineBuff.startsWith("endsolid") || lineBuff.startsWith("end solid"))
00187 {
00188 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00189 m_CurrentFace.clear();
00190 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00191 m_VertexBulk.clear();
00192 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00193 m_NormalBulk.clear();
00194
00195 m_pCurrentMesh->finish();
00196 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00197 m_pCurrentMesh= NULL;
00198 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00199 return;
00200 }
00201
00202 if (lineBuff.startsWith("solid"))
00203 {
00204
00205 lineBuff.remove(0, 5);
00206 lineBuff= lineBuff.trimmed();
00207 m_pCurrentMesh= new GLC_Mesh();
00208 m_pCurrentMesh->setName(lineBuff);
00209 return;
00210 }
00211
00213
00214 if (!lineBuff.startsWith("facet normal"))
00215 {
00216 QString message= "GLC_StlToWorld::scanFacet : \"facet normal\" not found!";
00217 message.append("\nAt line : ");
00218 message.append(QString::number(m_CurrentLineNumber));
00219 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00220 clear();
00221 throw(fileFormatException);
00222 }
00223 lineBuff.remove(0,12);
00224 lineBuff= lineBuff.trimmed().toLower();
00225 GLC_Vector3df cur3dVect= extract3dVect(lineBuff);
00226 for (int i= 0; i < 3; ++i)
00227 {
00228 m_NormalBulk.append(cur3dVect.x());
00229 m_NormalBulk.append(cur3dVect.y());
00230 m_NormalBulk.append(cur3dVect.z());
00231 }
00232
00234 ++m_CurrentLineNumber;
00235 lineBuff= m_StlStream.readLine();
00236 lineBuff= lineBuff.trimmed().toLower();
00237
00238 if (!lineBuff.startsWith("outer loop"))
00239 {
00240 QString message= "GLC_StlToWorld::scanFacet : \"outer loop\" not found!";
00241 message.append("\nAt line : ");
00242 message.append(QString::number(m_CurrentLineNumber));
00243 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00244 clear();
00245 throw(fileFormatException);
00246 }
00247
00249
00250 for (int i= 0; i < 3; ++i)
00251 {
00252 ++m_CurrentLineNumber;
00253 lineBuff= m_StlStream.readLine();
00254 lineBuff= lineBuff.trimmed().toLower();
00255
00256 if (!lineBuff.startsWith("vertex"))
00257 {
00258 QString message= "GLC_StlToWorld::scanFacet : \"vertex\" not found!";
00259 message.append("\nAt line : ");
00260 message.append(QString::number(m_CurrentLineNumber));
00261 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00262 clear();
00263 throw(fileFormatException);
00264 }
00265 lineBuff.remove(0,6);
00266 lineBuff= lineBuff.trimmed();
00267
00268 cur3dVect= extract3dVect(lineBuff);
00269 m_VertexBulk.append(cur3dVect.x());
00270 m_VertexBulk.append(cur3dVect.y());
00271 m_VertexBulk.append(cur3dVect.z());
00272
00273 m_CurrentFace.append(m_CurrentIndex);
00274 ++m_CurrentIndex;
00275 }
00276
00278 ++m_CurrentLineNumber;
00279 lineBuff= m_StlStream.readLine();
00280 lineBuff= lineBuff.trimmed().toLower();
00281
00282 if (!lineBuff.startsWith("endloop"))
00283 {
00284 QString message= "GLC_StlToWorld::scanFacet : \"endloop\" not found!";
00285 message.append("\nAt line : ");
00286 message.append(QString::number(m_CurrentLineNumber));
00287 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00288 clear();
00289 throw(fileFormatException);
00290 }
00291
00293 ++m_CurrentLineNumber;
00294 lineBuff= m_StlStream.readLine();
00295 lineBuff= lineBuff.trimmed().toLower();
00296
00297 if (!lineBuff.startsWith("endfacet"))
00298 {
00299 QString message= "GLC_StlToWorld::scanFacet : \"endfacet\" not found!";
00300 message.append("\nAt line : ");
00301 message.append(QString::number(m_CurrentLineNumber));
00302 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00303 clear();
00304 throw(fileFormatException);
00305 }
00306
00307 }
00308
00309
00310 GLC_Vector3df GLC_StlToWorld::extract3dVect(QString &line)
00311 {
00312 float x=0.0f;
00313 float y=0.0f;
00314 float z=0.0f;
00315
00316 GLC_Vector3df vectResult;
00317 QTextStream stringVecteur(&line);
00318
00319 QString xString, yString, zString;
00320
00321 if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00322 {
00323 bool xOk, yOk, zOk;
00324 x= xString.toFloat(&xOk);
00325 y= yString.toFloat(&yOk);
00326 z= zString.toFloat(&zOk);
00327 if (!(xOk && yOk && zOk))
00328 {
00329 QString message= "GLC_StlToWorld::extract3dVect : failed to convert vector component to float";
00330 message.append("\nAt ligne : ");
00331 message.append(QString::number(m_CurrentLineNumber));
00332 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00333 clear();
00334 throw(fileFormatException);
00335 }
00336 else
00337 {
00338 vectResult.setVect(x, y, z);
00339 }
00340 }
00341
00342 return vectResult;
00343
00344 }
00345
00346 void GLC_StlToWorld::LoadBinariStl(QFile &file)
00347 {
00348
00349 int currentQuantumValue= 0;
00350 int previousQuantumValue= 0;
00351
00352 QDataStream stlBinFile(&file);
00353 stlBinFile.setVersion(QDataStream::Qt_4_6);
00354 stlBinFile.setFloatingPointPrecision(QDataStream::SinglePrecision);
00355 stlBinFile.setByteOrder(QDataStream::LittleEndian);
00356
00357
00358 int SkipedData= stlBinFile.skipRawData(80);
00359
00360 if (-1 == SkipedData)
00361 {
00362 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to skip Header of binary STL";
00363 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00364 clear();
00365 throw(fileFormatException);
00366 }
00367
00368 quint32 numberOfFacet= 0;
00369 stlBinFile >> numberOfFacet;
00370
00371 if (QDataStream::Ok != stlBinFile.status())
00372 {
00373 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the number of facets of binary STL";
00374 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00375 clear();
00376 throw(fileFormatException);
00377 }
00378 for (quint32 i= 0; i < numberOfFacet; ++i)
00379 {
00380
00381 float nx, ny, nz;
00382 stlBinFile >> nx >> ny >> nz;
00383
00384 if (QDataStream::Ok != stlBinFile.status())
00385 {
00386 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Normal of binary STL";
00387 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00388 clear();
00389 throw(fileFormatException);
00390 }
00391
00392
00393 for (int j= 0; j < 3; ++j)
00394 {
00395 float x, y, z;
00396 stlBinFile >> x >> y >> z;
00397
00398 if (QDataStream::Ok != stlBinFile.status())
00399 {
00400 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Vertex of binary STL";
00401 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00402 clear();
00403 throw(fileFormatException);
00404 }
00405 m_VertexBulk.append(x);
00406 m_VertexBulk.append(y);
00407 m_VertexBulk.append(z);
00408
00409 m_NormalBulk.append(nx);
00410 m_NormalBulk.append(ny);
00411 m_NormalBulk.append(nz);
00412
00413 m_CurrentFace.append(m_CurrentIndex);
00414 ++m_CurrentIndex;
00415 }
00416 currentQuantumValue = static_cast<int>((static_cast<double>(i + 1) / numberOfFacet) * 100);
00417 if (currentQuantumValue > previousQuantumValue)
00418 {
00419 emit currentQuantum(currentQuantumValue);
00420 }
00421 previousQuantumValue= currentQuantumValue;
00422
00423
00424 stlBinFile.skipRawData(2);
00425
00426 }
00427 }
00428