ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvObject.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvObject.h"
9 
10 // Qt
11 #include <QSettings>
12 
13 #ifdef USE_VLD
14 // VLD
15 #include <vld.h>
16 #endif
17 
18 // System
19 #include <stdint.h>
20 
61 const unsigned c_currentDBVersion = 57; // 5.7
62 
66 
68  if (generator == s_uniqueIDGenerator) return;
69 
70  // we hope that the previous generator has not been used!
71  assert(!s_uniqueIDGenerator || s_uniqueIDGenerator->getLast() == 0);
72  s_uniqueIDGenerator = generator;
73 }
74 
76  return s_uniqueIDGenerator;
77 }
78 
80 
82  if (!s_uniqueIDGenerator) {
83  assert(false);
86  }
87  return s_uniqueIDGenerator->fetchOne();
88 }
89 
91  return s_uniqueIDGenerator ? s_uniqueIDGenerator->getLast() : 0;
92 }
93 
95  : m_name(name.isEmpty() ? "unnamed" : name),
96  m_baseName(m_name),
97  m_filePath(QString(m_baseName) + ".bin"),
98  m_removeFlag(false),
99  m_flags(CC_ENABLED),
100  m_uniqueID(GetNextUniqueID()) {}
101 
103  : m_name(object.m_name),
104  m_baseName(object.m_baseName),
105  m_filePath(object.m_filePath),
106  m_removeFlag(false),
107  m_flags(object.m_flags),
108  m_uniqueID(GetNextUniqueID()) {}
109 
110 void ccObject::setUniqueID(unsigned ID) {
111  m_uniqueID = ID;
112 
113  // updates last unique ID
115  s_uniqueIDGenerator->update(m_uniqueID);
116  else
117  assert(false);
118 }
119 
120 void ccObject::setFlagState(CV_OBJECT_FLAG flag, bool state) {
121  if (state)
122  m_flags |= unsigned(flag);
123  else
124  m_flags &= (~unsigned(flag));
125 }
126 
127 bool ccObject::toFile(QFile& out, short dataVersion) const {
128  assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
129 
130  // Version validation
131  if (dataVersion < 34) {
132  assert(false);
133  return false;
134  }
135 
136  // class ID (dataVersion>=20)
137  // DGM: on 64 bits since version 34
138  uint64_t classID = static_cast<uint64_t>(getClassID());
139  if (out.write((const char*)&classID, 8) < 0) return WriteError();
140 
141  // unique ID (dataVersion>=20)
142  // DGM: this ID will be useful to recreate dynamic links between entities!
143  uint32_t uniqueID = (uint32_t)m_uniqueID;
144  if (out.write((const char*)&uniqueID, 4) < 0) return WriteError();
145 
146  // name (dataVersion>=22)
147  {
148  QDataStream outStream(&out);
149  outStream << m_name;
150  }
151 
152  // flags (dataVersion>=20)
153  uint32_t objFlags = (uint32_t)m_flags;
154  if (out.write((const char*)&objFlags, 4) < 0) return WriteError();
155 
156  // meta data (dataVersion>=30)
157  {
158  // check for valid pieces of meta-data
159  // DGM: some pieces of meta-data can't be properly streamed (the ones
160  // relying on 'Q_DECLARE_METATYPE' calls typically)
161  uint32_t validMetaDataCount = 0;
162  for (QVariantMap::const_iterator it = m_metaData.begin();
163  it != m_metaData.end(); ++it) {
164  if (!it.key().contains(".nosave")) {
165  ++validMetaDataCount;
166  }
167  }
168 
169  // count
170  if (out.write((const char*)&validMetaDataCount, 4) < 0)
171  return WriteError();
172 
173  //"key + value" pairs
174  QDataStream outStream(&out);
175  for (QVariantMap::const_iterator it = m_metaData.begin();
176  it != m_metaData.end(); ++it) {
177  if (!it.key().contains(".nosave")) {
178  outStream << it.key();
179  outStream << it.value();
180  }
181  }
182  }
183 
184  return true;
185 }
186 
187 short ccObject::minimumFileVersion() const { return 34; }
188 
189 CV_CLASS_ENUM ccObject::ReadClassIDFromFile(QFile& in, short dataVersion) {
190  assert(in.isOpen() && (in.openMode() & QIODevice::ReadOnly));
191 
192  // class ID (on 32 bits between version 2.0 and 3.3, then 64 bits from
193  // version 3.4)
195  if (dataVersion < 34) {
196  uint32_t _classID = 0;
197  if (in.read((char*)&_classID, 4) < 0) return ReadError();
198  classID = static_cast<CV_CLASS_ENUM>(_classID);
199  } else {
200  uint64_t _classID = 0;
201  if (in.read((char*)&_classID, 8) < 0) return ReadError();
202  classID = static_cast<CV_CLASS_ENUM>(_classID);
203  }
204 
205  return classID;
206 }
207 
208 QVariant ccObject::getMetaData(const QString& key) const {
209  return m_metaData.value(key, QVariant());
210 }
211 
212 bool ccObject::removeMetaData(const QString& key) {
213  return m_metaData.remove(key) != 0;
214 }
215 
216 void ccObject::setMetaData(const QString& key, const QVariant& data) {
217  m_metaData.insert(key, data);
218 }
219 
220 void ccObject::setMetaData(const QVariantMap& dataset,
221  bool overwrite /*=false*/) {
222  for (QVariantMap::const_iterator it = dataset.begin(); it != dataset.end();
223  ++it) {
224  if (overwrite || !m_metaData.contains(it.key())) {
225  m_metaData[it.key()] = it.value();
226  }
227  }
228 }
229 
230 bool ccObject::hasMetaData(const QString& key) const {
231  return m_metaData.contains(key);
232 }
233 
234 bool ccObject::fromFile(QFile& in,
235  short dataVersion,
236  int flags,
237  LoadedIDMap& oldToNewIDMap) {
238  assert(in.isOpen() && (in.openMode() & QIODevice::ReadOnly));
239 
240  if (dataVersion < 20) return CorruptError();
241 
242  // DGM: if we are here, we assume the class ID has already been read!
243  // Call ccObject::readClassIDFromFile if necessary
245  // uint32_t classID = 0;
246  // if (in.read((char*)&classID,4) < 0)
247  // return ReadError();
248 
249  // unique ID (dataVersion>=20)
250  uint32_t uniqueID = 0;
251  if (in.read((char*)&uniqueID, 4) < 0) return ReadError();
252  // DGM: this ID will be useful to recreate dynamic links between entities
253  // later!
254  if (oldToNewIDMap.contains(uniqueID)) {
255  CVLog::Warning(QString("Malformed file: uniqueID #%1 is used several "
256  "times! (not that unique ;)")
257  .arg(uniqueID));
258  }
259  oldToNewIDMap.insert(uniqueID, m_uniqueID);
260 
261  // name
262  if (dataVersion < 22) // old style
263  {
264  char name[256];
265  if (in.read(name, 256) < 0) return ReadError();
266  setName(name);
267  } else //(dataVersion>=22)
268  {
269  QDataStream inStream(&in);
270  inStream >> m_name;
271  }
272 
273  // flags (dataVersion>=20)
274  uint32_t objFlags = 0;
275  if (in.read((char*)&objFlags, 4) < 0) return ReadError();
276  m_flags = (unsigned)objFlags;
277 
278  // meta data (dataVersion>=30)
279  if (dataVersion >= 30) {
280  // count
281  uint32_t metaDataCount = 0;
282  if (in.read((char*)&metaDataCount, 4) < 0) return ReadError();
283 
284  //"key + value" pairs
285  for (uint32_t i = 0; i < metaDataCount; ++i) {
286  QDataStream inStream(&in);
287  QString key;
288  QVariant value;
289  inStream >> key;
290 #if 1 // patch to overcome the issue with LAS vlrs not being readable anymore
291  // as QVariant object with Qt 6
292  if (key == "LAS.vlrs") {
293  inStream.skipRawData(
294  16); // size of a partial QVariant object on Windows
295  quint64 vlrSize = 0;
296  inStream >> vlrSize;
297  for (quint64 i = 0; i < vlrSize; ++i) {
298  inStream.skipRawData(sizeof(uint16_t));
299  inStream.skipRawData(16 * sizeof(char));
300  inStream.skipRawData(sizeof(uint16_t));
301  uint16_t record_length_after_header;
302  inStream >> record_length_after_header;
303  inStream.skipRawData(32 * sizeof(char));
304  inStream.skipRawData(record_length_after_header);
305  }
306 
307  quint64 extraScalarFieldCount = 0;
308  inStream >> extraScalarFieldCount;
309  inStream.skipRawData(272 * extraScalarFieldCount);
310  } else
311 #endif
312  {
313  inStream >> value;
314  setMetaData(key, value);
315  }
316  }
317  }
318 
319  return true;
320 }
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
Definition: CVTypes.h:97
CV_OBJECT_FLAG
Type of a single scalar field value.
Definition: CVTypes.h:28
@ CC_ENABLED
Definition: CVTypes.h:30
std::string name
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
Generic "CLOUDVIEWER Object" template.
Definition: ecvObject.h:49
short minimumFileVersion() const override
Returns the minimum file version required to save this instance.
Definition: ecvObject.cpp:187
static ccUniqueIDGenerator::Shared GetUniqueIDGenerator()
Returns the unique ID generator.
Definition: ecvObject.cpp:75
static unsigned GetCurrentDBVersion()
Returns current database version.
Definition: ecvObject.cpp:79
unsigned m_flags
Object flags.
Definition: ecvObject.h:227
void setMetaData(const QString &key, const QVariant &data)
Sets a meta-data element.
Definition: ecvObject.cpp:216
static CV_CLASS_ENUM ReadClassIDFromFile(QFile &in, short dataVersion)
Helper: reads out class ID from a binary stream.
Definition: ecvObject.cpp:189
QVariant getMetaData(const QString &key) const
Returns a given associated meta data.
Definition: ecvObject.cpp:208
virtual void setUniqueID(unsigned ID)
Changes unique ID.
Definition: ecvObject.cpp:110
bool hasMetaData(const QString &key) const
Returns whether a meta-data element with the given key exists or not.
Definition: ecvObject.cpp:230
virtual void setName(const QString &name)
Sets object name.
Definition: ecvObject.h:75
virtual CV_CLASS_ENUM getClassID() const =0
Returns class ID.
ccObject(QString name=QString())
Default constructor.
Definition: ecvObject.cpp:94
bool removeMetaData(const QString &key)
Removes a given associated meta-data.
Definition: ecvObject.cpp:212
QVariantMap m_metaData
Associated meta-data.
Definition: ecvObject.h:230
static unsigned GetLastUniqueID()
Returns last assigned unique ID.
Definition: ecvObject.cpp:90
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
Definition: ecvObject.cpp:127
virtual void setFlagState(CV_OBJECT_FLAG flag, bool state)
Sets flag state.
Definition: ecvObject.cpp:120
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Reimplemented from ccSerializableObject::fromFile.
Definition: ecvObject.cpp:234
static void SetUniqueIDGenerator(ccUniqueIDGenerator::Shared generator)
Sets the unique ID generator.
Definition: ecvObject.cpp:67
static unsigned GetNextUniqueID()
Returns a new unassigned unique ID.
Definition: ecvObject.cpp:81
QString m_name
Object name.
Definition: ecvObject.h:219
static bool CorruptError()
Sends a custom error message (corrupted file) and returns 'false'.
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
static bool ReadError()
Sends a custom error message (read error) and returns 'false'.
static bool WriteError()
Sends a custom error message (write error) and returns 'false'.
QSharedPointer< ccUniqueIDGenerator > Shared
Shared type.
Definition: ecvObject.h:28
static ccUniqueIDGenerator::Shared s_uniqueIDGenerator(new ccUniqueIDGenerator)
const unsigned c_currentDBVersion
Definition: ecvObject.cpp:61
GraphType data
Definition: graph_cut.cc:138
@ OBJECT
Definition: CVTypes.h:102