GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_bsrep.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  *****************************************************************************/
23 
24 #include "glc_bsrep.h"
25 #include "../glc_fileformatexception.h"
26 #include "../glc_tracelog.h"
27 
28 // The binary rep suffix
29 const QString GLC_BSRep::m_Suffix("BSRep");
30 
31 // The binary rep magic number
32 const QUuid GLC_BSRep::m_Uuid("{d6f97789-36a9-4c2e-b667-0e66c27f839f}");
33 
34 // The binary rep version
35 const quint32 GLC_BSRep::m_Version= 103;
36 
37 // Mutex used by compression
39 
40 // Default constructor
41 GLC_BSRep::GLC_BSRep(const QString& fileName, bool useCompression)
42 : m_FileInfo()
43 , m_pFile(NULL)
44 , m_DataStream()
45 , m_UseCompression(useCompression)
46 , m_CompressionLevel(-1)
47 {
48  setAbsoluteFileName(fileName);
49  m_DataStream.setVersion(QDataStream::Qt_4_6);
50  m_DataStream.setFloatingPointPrecision(QDataStream::SinglePrecision);
51 }
52 
53 // Copy constructor
55 : m_FileInfo(binaryRep.m_FileInfo)
56 , m_pFile(NULL)
57 , m_DataStream()
58 , m_UseCompression(binaryRep.m_UseCompression)
59 , m_CompressionLevel(binaryRep.m_CompressionLevel)
60 {
61  m_DataStream.setVersion(QDataStream::Qt_4_6);
62  m_DataStream.setFloatingPointPrecision(binaryRep.m_DataStream.floatingPointPrecision());
63 }
64 
66 {
67  delete m_pFile;
68 }
69 
70 // Return true if the binary rep is up to date
71 bool GLC_BSRep::isUsable(const QDateTime& timeStamp)
72 {
73  bool isUpToDate= false;
74  if (open(QIODevice::ReadOnly, NULL))
75  {
76  if (headerIsOk())
77  {
78  isUpToDate= timeStampOk(timeStamp);
79  isUpToDate= isUpToDate && close();
80  }
81  }
82  else
83  {
84  QString message(QString("GLC_BSRep::loadRep Enable to open the file ") + m_FileInfo.fileName());
85  GLC_FileFormatException fileFormatException(message, m_FileInfo.fileName(), GLC_FileFormatException::FileNotFound);
86  close();
87  throw(fileFormatException);
88  }
89 
90  if (!isUpToDate && GLC_TraceLog::isEnable())
91  {
92  QStringList stringList("GLC_BSRep::isUsable");
93  stringList.append("File " + m_FileInfo.filePath() + " not Usable");
94  GLC_TraceLog::addTrace(stringList);
95  }
96  return isUpToDate;
97 }
98 
100 // name Get Functions
102 // Load the binary rep
104 {
105  GLC_3DRep loadedRep;
106 
107  if (open(QIODevice::ReadOnly, pFile))
108  {
109  if (headerIsOk())
110  {
111  timeStampOk(QDateTime());
114  bool useCompression;
115  m_DataStream >> useCompression;
116  if (useCompression)
117  {
118  QByteArray CompresseBuffer;
119  m_DataStream >> CompresseBuffer;
120  QByteArray uncompressedBuffer= qUncompress(CompresseBuffer);
121  uncompressedBuffer.squeeze();
122  CompresseBuffer.clear();
123  CompresseBuffer.squeeze();
124  QDataStream bufferStream(uncompressedBuffer);
125  bufferStream >> loadedRep;
126  }
127  else
128  {
129  m_DataStream >> loadedRep;
130  }
131  loadedRep.setFileName(m_FileInfo.filePath());
132 
133  if (!close())
134  {
135  QString message(QString("GLC_BSRep::loadRep An error occur when loading file ") + m_FileInfo.fileName());
136  GLC_FileFormatException fileFormatException(message, m_FileInfo.fileName(), GLC_FileFormatException::WrongFileFormat);
137  throw(fileFormatException);
138  }
139  }
140  else
141  {
142  QString message(QString("GLC_BSRep::loadRep File not supported ") + m_FileInfo.fileName());
143  GLC_FileFormatException fileFormatException(message, m_FileInfo.fileName(), GLC_FileFormatException::FileNotSupported);
144  close();
145  throw(fileFormatException);
146  }
147  }
148  else
149  {
150  QString message(QString("GLC_BSRep::loadRep Enable to open the file ") + m_FileInfo.fileName());
151  GLC_FileFormatException fileFormatException(message, m_FileInfo.fileName(), GLC_FileFormatException::FileNotFound);
152  close();
153  throw(fileFormatException);
154  }
155 
156 
157  return loadedRep;
158 }
159 
160 // Return the bounding box of the binary representation
162 {
164 
165  if (open(QIODevice::ReadOnly, NULL))
166  {
167  if (headerIsOk())
168  {
169  timeStampOk(QDateTime());
170 
172  }
173  close();
174  }
175  return boundingBox;
176 }
177 
178 // Return bsrep suffix
180 {
181  return m_Suffix;
182 }
183 
185 {
186  return m_Version;
187 }
188 
190 //name Set Functions
192 // Set the binary representation file name
193 void GLC_BSRep::setAbsoluteFileName(const QString& fileName)
194 {
195  m_FileInfo.setFile(fileName);
196  if (m_FileInfo.suffix() != m_Suffix)
197  {
198  m_FileInfo.setFile(fileName + '.' + m_Suffix);
199  }
200 
201 }
202 
203 // Save the GLC_3DRep in serialised binary
204 bool GLC_BSRep::save(const GLC_3DRep& rep)
205 {
206 
208  bool saveOk= open(QIODevice::WriteOnly, NULL);
209  if (saveOk)
210  {
211  writeHeader(rep.lastModified());
212 
213  // Representation Bounding Box
214  m_DataStream << rep.boundingBox();
215 
216  // Compression usage
217 
218  if (m_UseCompression && (rep.faceCount() < 1000000))
219  {
220  m_DataStream << true;
221  QByteArray uncompressedBuffer;
222  {
223  QBuffer buffer(&uncompressedBuffer);
224  buffer.open(QIODevice::WriteOnly);
225  QDataStream bufferStream(&buffer);
226  bufferStream << rep;
227  }
228  m_DataStream << qCompress(uncompressedBuffer, m_CompressionLevel);
229  }
230  else
231  {
232  m_DataStream << false;
233  // Binary representation geometry
234  // Add the rep
235  m_DataStream << rep;
236  }
237 
238  // Flag the file
239  qint64 offset= sizeof(QUuid);
240  offset+= sizeof(quint32);
241 
242  m_pFile->seek(offset);
243  bool writeOk= true;
244  m_DataStream << writeOk;
245  // Close the file
246  saveOk= close();
247  }
248  return saveOk;
249 }
250 
251 
252 // Open the file
253 bool GLC_BSRep::open(QIODevice::OpenMode mode, QFile* pFile)
254 {
255  bool openOk= m_FileInfo.exists() || ((NULL != pFile) && pFile->exists());
256  if (openOk || (mode == QIODevice::WriteOnly))
257  {
258  m_DataStream.setDevice(NULL);
259  if (NULL != pFile)
260  {
261  m_pFile= pFile;
262  }
263  else
264  {
265  m_pFile= new QFile(m_FileInfo.filePath());
266  }
267 
268  openOk= m_pFile->open(mode);
269  if (openOk)
270  {
271  m_DataStream.setDevice(m_pFile);
272  }
273  }
274  else if (GLC_TraceLog::isEnable())
275  {
276  QStringList stringList("GLC_BSRep::open");
277  stringList.append("File " + m_FileInfo.filePath() + " doesn't exists");
278  GLC_TraceLog::addTrace(stringList);
279  }
280 
281  return openOk;
282 }
283 
284 // Close the file
286 {
287  Q_ASSERT(m_pFile != NULL);
288  Q_ASSERT(m_DataStream.device() != NULL);
289  bool closeOk= m_DataStream.status() == QDataStream::Ok;
290  m_DataStream.setDevice(NULL);
291  m_pFile->close();
292  delete m_pFile;
293  m_pFile= NULL;
294 
295  return closeOk;
296 }
297 
298 // Write the header
299 void GLC_BSRep::writeHeader(const QDateTime& dateTime)
300 {
301  Q_ASSERT(m_pFile != NULL);
302  Q_ASSERT(m_DataStream.device() != NULL);
303 
304  // Binary representation Header
305  // Add the magic number
306  m_DataStream << m_Uuid;
307  // Add the version
309  bool writeFinished= false;
310  m_DataStream << writeFinished;
311 
312  // Set the version of the data stream
313  m_DataStream.setVersion(QDataStream::Qt_4_6);
314 
315  // Add the time stamp
316  m_DataStream << dateTime;
317 }
318 
319 // Check the header
321 {
322  Q_ASSERT(m_pFile != NULL);
323  Q_ASSERT(m_DataStream.device() != NULL);
324  Q_ASSERT(m_pFile->openMode() == QIODevice::ReadOnly);
325 
326  QUuid uuid;
327  quint32 version;
328  bool writeFinished;
329 
330  m_DataStream >> uuid;
332  m_DataStream >> writeFinished;
333 
334  // Set the version of the data stream
335  m_DataStream.setVersion(QDataStream::Qt_4_6);
336 
337  bool headerOk= (uuid == m_Uuid) && (version <= m_Version) && (version > 101) && writeFinished;
338 
339  return headerOk;
340 }
341 
342 // Check the time Stamp
343 bool GLC_BSRep::timeStampOk(const QDateTime& timeStamp)
344 {
345  Q_ASSERT(m_pFile != NULL);
346  Q_ASSERT(m_DataStream.device() != NULL);
347  Q_ASSERT(m_pFile->openMode() == QIODevice::ReadOnly);
348 
349  QDateTime dateTime;
350  m_DataStream >> dateTime;
351 
352  bool timeStampOk= !timeStamp.isValid() || (dateTime == timeStamp);
353  return timeStampOk;
354 }
355 

©2005-2013 Laurent Ribon