CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxRegistrationTransform.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 
14 //#include <QtXML>
15 #include <QDomElement>
16 #include "cxTime.h"
17 #include "cxTypeConversions.h"
18 #include "cxLogger.h"
19 
20 namespace cx
21 {
22 
23 // --------------------------------------------------------
24 RegistrationHistoryPtr RegistrationHistory::mNull;
25 // --------------------------------------------------------
26 
27 
31 {
32 public:
33  virtual void addXml(QDomNode& parentNode) const
34  {
35  }
36  virtual void parseXml(QDomNode& dataNode)
37  {
38  }
39 
41  {
42  }
43  virtual void setRegistration(const Transform3D& transform)
44  {
45  }
46  virtual void addOrUpdateRegistration(const QDateTime& oldTime, const RegistrationTransform& newTransform)
47  {
48  }
49 
50  virtual void setParentSpace(const QString& newParent)
51  {
52  }
53  virtual void addParentSpace(const QString& newParent)
54  {
55  }
56  virtual void addParentSpace(const ParentSpace& newParent)
57  {
58  }
59  virtual void updateParentSpace(const QDateTime& oldTime, const ParentSpace& newParent)
60  {
61  }
62 
63  virtual std::vector<RegistrationTransform> getData() const
64  {
65  return std::vector<RegistrationTransform>();
66  }
67  virtual std::vector<ParentSpace> getParentSpaces() const
68  {
69  return std::vector<ParentSpace>();
70  }
71  virtual void removeNewerThan(const QDateTime& timestamp)
72  {
73  }
74  virtual void setActiveTime(const QDateTime& timestamp)
75  {
76  }
77  virtual QDateTime getActiveTime() const
78  {
79  return QDateTime();
80  }
82  {
83  return RegistrationTransform();
84  }
86  {
87  return ParentSpace();
88  }
89  virtual void clear()
90  {
91  }
92  virtual bool isNull() const
93  {
94  return true;
95  }
96 };
97 
98 //---------------------------------------------------------
99 //------- RegistrationTransform -------------------------
100 //---------------------------------------------------------
101 
103  mValue(Transform3D::Identity()), mTemp(false)
104 {
105 }
106 
107 RegistrationTransform::RegistrationTransform(const Transform3D& value, const QDateTime& timestamp, const QString& type, bool tempTransform)
108 {
109  mValue = value;
110  mTimestamp = timestamp;
111  mType = type;
112  mTemp = tempTransform;
113 }
114 
115 void RegistrationTransform::addXml(QDomNode& parentNode) const
116 {
117  QDomDocument doc = parentNode.ownerDocument();
118  QDomElement base = doc.createElement("registrationTransform");
119  parentNode.appendChild(base);
120 
121  base.setAttribute("timestamp", mTimestamp.toString(timestampSecondsFormat()));
122  base.setAttribute("type", mType);
123 
124  if (!mFixed.isEmpty())
125  base.setAttribute("fixed", mFixed);
126  if (!mMoving.isEmpty())
127  base.setAttribute("moving", mMoving);
128 
129  base.appendChild(doc.createTextNode("\n" + qstring_cast(mValue)));
130 }
131 
132 void RegistrationTransform::parseXml(QDomNode& dataNode)
133 {
134  if (dataNode.isNull())
135  return;
136 
137  QDomElement base = dataNode.toElement();
138 
139  mTimestamp = QDateTime::fromString(base.attribute("timestamp"), timestampSecondsFormat());
140  mType = base.attribute("type");
141  mValue = Transform3D::fromString(base.text());
142  mFixed = base.attribute("fixed");
143  mMoving = base.attribute("moving");
144 }
145 
147 {
148  return lhs.mTimestamp < rhs.mTimestamp;
149 }
150 
152 {
153  return similar(lhs.mValue, rhs.mValue, 1.0E-3) && (lhs.mTimestamp == rhs.mTimestamp) && (lhs.mType == rhs.mType);
154 }
155 
156 //---------------------------------------------------------
157 //------- RegistrationTransform -------------------------
158 //---------------------------------------------------------
159 
161 {
162 
163 }
164 
165 ParentSpace::ParentSpace(const QString& uid, const QDateTime& timestamp, const QString& type)
166 {
167  mUid = uid;
168  mTimestamp = timestamp;
169  mType = type;
170 }
171 
172 void ParentSpace::addXml(QDomNode& parentNode) const
173 {
174  QDomDocument doc = parentNode.ownerDocument();
175  QDomElement base = doc.createElement("parentFrame");
176  parentNode.appendChild(base);
177 
178  base.setAttribute("value", mUid);
179  base.setAttribute("timestamp", mTimestamp.toString(timestampSecondsFormat()));
180  base.setAttribute("type", mType);
181 }
182 
183 void ParentSpace::parseXml(QDomNode& dataNode)
184 {
185  if (dataNode.isNull())
186  return;
187 
188  QDomElement base = dataNode.toElement();
189 
190  mTimestamp = QDateTime::fromString(base.attribute("timestamp"), timestampSecondsFormat());
191  mType = base.attribute("type");
192  mUid = base.attribute("value");
193 }
194 
195 bool operator<(const ParentSpace& lhs, const ParentSpace& rhs)
196 {
197  return lhs.mTimestamp < rhs.mTimestamp;
198 }
199 
200 bool operator==(const ParentSpace& lhs, const ParentSpace& rhs)
201 {
202  return (lhs.mUid == rhs.mUid) && (lhs.mTimestamp == rhs.mTimestamp) && (lhs.mType == rhs.mType);
203 }
204 
205 //---------------------------------------------------------
206 //------- RegistrationHistory -------------------------
207 //---------------------------------------------------------
208 
210 {
211  if (!mNull)
212  mNull.reset(new RegistrationHistoryNull);
213  return mNull;
214 }
215 
216 void RegistrationHistory::addXml(QDomNode& parentNode) const
217 {
218  QDomDocument doc = parentNode.ownerDocument();
219  QDomElement base = doc.createElement("registrationHistory");
220  parentNode.appendChild(base);
221 
222  QDomElement currentTime = doc.createElement("currentTime");
223  currentTime.appendChild(doc.createTextNode(mCurrentTime.toString(timestampSecondsFormat())));
224  base.appendChild(currentTime);
225 
226  for (unsigned i = 0; i < mData.size(); ++i)
227  {
228  mData[i].addXml(base);
229  }
230  for (unsigned i = 0; i < mParentSpaces.size(); ++i)
231  {
232  mParentSpaces[i].addXml(base);
233  }
234 }
235 
236 void RegistrationHistory::parseXml(QDomNode& dataNode)
237 {
238  if (dataNode.isNull())
239  return;
240 
241  mData.clear();
242  QString currentTimeRaw = dataNode.namedItem("currentTime").toElement().text();
243  QDateTime currentTime = QDateTime::fromString(currentTimeRaw, timestampSecondsFormat());
244 
245  // iterate over all data elements
246  QDomElement currentElem = dataNode.firstChildElement("registrationTransform");
247  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("registrationTransform"))
248  {
250  transform.parseXml(currentElem);
251  mData.push_back(transform);
252  }
253 
254  // iterate over all data elements
255  currentElem = dataNode.firstChildElement("parentFrame");
256  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("parentFrame"))
257  {
259  transform.parseXml(currentElem);
260  mParentSpaces.push_back(transform);
261  }
262 
263  std::sort(mData.begin(), mData.end());
264  std::sort(mParentSpaces.begin(), mParentSpaces.end());
265  setActiveTime(currentTime); // update cache
266 }
267 
269 {
270  mData.clear();
271  mCurrentTime = QDateTime();
272  mTransformCache = RegistrationTransform();
273 }
274 
279 void RegistrationHistory::addRegistrationInternal(const RegistrationTransform& transform)
280 {
281  if (std::count(mData.begin(), mData.end(), transform)) // ignore if already present
282  return;
283 
284  mData.push_back(transform);
285  std::sort(mData.begin(), mData.end());
286 
287  bool silent = transform.mTemp;
288  setActiveTime(QDateTime()); // reset to last registration when reregistering.
289 }
290 
297 void RegistrationHistory::addOrUpdateRegistration(const QDateTime& oldTime, const RegistrationTransform& newTransform)
298 {
299  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
300  {
301  if ((iter->mTimestamp == oldTime)
302  && oldTime.isValid()
303  && iter->mTemp)
304  {
305  mData.erase(iter);
306  break;
307  }
308  }
309  this->addRegistrationInternal(newTransform);
310 }
311 
316 {
317  bool changed = true;
318  if (similar(getCurrentRegistration().mValue, transform))
319  {
320  changed = false;
321  }
322  mData.clear();
323  this->addRegistrationInternal(RegistrationTransform(transform));
324  if (changed)
325  {
326  emit currentChanged();
327  }
328 }
329 
333 void RegistrationHistory::setParentSpace(const QString& newParent)
334 {
335  mParentSpaces.clear();
336  this->addParentSpace(ParentSpace(newParent));
337 }
338 
339 void RegistrationHistory::addParentSpace(const QString& newParent)
340 {
341  this->addParentSpace(ParentSpace(newParent, QDateTime::currentDateTime(), "Set Parent Frame"));
342 }
343 
345 {
346  for (int i = 0; i < mParentSpaces.size(); ++i)
347  {
348  if(mParentSpaces[i].mUid == newParent.mUid)
349  return;// ignore if already present
350  }
351 
352  mParentSpaces.push_back(newParent);
353  std::sort(mParentSpaces.begin(), mParentSpaces.end());
354  setActiveTime(QDateTime()); // reset to last registration when reregistering.
355 }
356 
357 void RegistrationHistory::updateParentSpace(const QDateTime& oldTime, const ParentSpace& newParent)
358 {
359  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
360  {
361  if (iter->mTimestamp != oldTime)
362  continue;
363  mParentSpaces.erase(iter);
364  break;
365  }
366  this->addParentSpace(newParent);
367 }
368 
370 {
371  return mParentSpaceCache;
372 }
373 
374 std::vector<RegistrationTransform> RegistrationHistory::getData() const
375 {
376  return mData;
377 }
378 
379 std::vector<ParentSpace> RegistrationHistory::getParentSpaces() const
380 {
381  return mParentSpaces;
382 }
383 
384 void RegistrationHistory::removeNewerThan(const QDateTime& timestamp)
385 {
386  if (!timestamp.isValid())
387  return;
388 
389  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end();)
390  {
391  if (iter->mTimestamp > timestamp)
392  {
393  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
394  << "): removed [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", " << iter->mType
395  << "]" << std::endl;
396  iter = mData.erase(iter);
397  }
398  else
399  {
400  ++iter;
401  }
402  }
403 
404  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end();)
405  {
406  if (iter->mTimestamp > timestamp)
407  {
408  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
409  << "): removed parent frame [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", "
410  << iter->mType << "]" << std::endl;
411  iter = mParentSpaces.erase(iter);
412  }
413  else
414  {
415  ++iter;
416  }
417  }
418 
419  setActiveTime(QDateTime());
420 }
421 
422 void RegistrationHistory::setCache(const RegistrationTransform& val, const ParentSpace& parent,
423  const QDateTime& timestamp)
424 {
425  if ((mTransformCache == val) && (mParentSpaceCache == parent) && (mCurrentTime == timestamp))
426  return;
427 
428  mCurrentTime = timestamp;
429  mTransformCache = val;
430  mParentSpaceCache = parent;
431 
432  emit currentChanged();
433 }
434 
438 void RegistrationHistory::setActiveTime(const QDateTime& timestamp)
439 {
441  ParentSpace parent;
442  // set to specified time
443  if (timestamp.isValid())
444  {
445  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
446  {
447  if (iter->mTimestamp <= timestamp)
448  val = *iter;
449  }
450  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
451  {
452  if (iter->mTimestamp <= timestamp)
453  parent = *iter;
454  }
455  }
456  else
457  {
458  if (!mData.empty())
459  val = mData.back();
460  if (!mParentSpaces.empty())
461  parent = mParentSpaces.back();
462  }
463 
464  setCache(val, parent, timestamp);
465 }
466 
468 {
469  return mCurrentTime;
470 }
471 
473 {
474  return mTransformCache;
475 }
476 
477 } // end namespace cx
478 
QString qstring_cast(const T &val)
virtual void setRegistration(const Transform3D &transform)
bool operator<(const Landmark &lhs, const Landmark &rhs)
Definition: cxLandmark.cpp:73
virtual std::vector< RegistrationTransform > getData() const
virtual void setParentSpace(const QString &newParent)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
virtual ParentSpace getCurrentParentSpace()
boost::shared_ptr< class RegistrationHistory > RegistrationHistoryPtr
Definition: cxDataManager.h:37
Definition of a parent space event.
virtual void addXml(QDomNode &parentNode) const
write internal state to node
static RegistrationHistoryPtr getNullObject()
virtual void setParentSpace(const QString &newParent)
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
virtual void addOrUpdateRegistration(const RegistrationTransform &transform)
QString timestampSecondsFormatNice()
Definition: cxTime.cpp:26
virtual void updateParentSpace(const QDateTime &oldTime, const ParentSpace &newParent)
virtual void setActiveTime(const QDateTime &timestamp)
virtual QDateTime getActiveTime() const
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
QString mUid
parent frame uid
virtual void clear()
reset all data loaded from xml
virtual void addXml(QDomNode &parentNode) const
write internal state to node
virtual std::vector< ParentSpace > getParentSpaces() const
QDateTime mTimestamp
time the transform was registrated.
virtual void addParentSpace(const QString &newParent)
QDateTime mTimestamp
time the transform was registrated.
void parseXml(QDomNode &dataNode)
read internal state from node
virtual std::vector< RegistrationTransform > getData() const
Transform3D mValue
value of transform
void addXml(QDomNode &parentNode) const
write internal state to node
virtual QDateTime getActiveTime() const
virtual RegistrationTransform getCurrentRegistration() const
virtual void removeNewerThan(const QDateTime &timestamp)
QString mType
description of the kind if registration (manual, patient, landmark, coregistration etc) ...
void parseXml(QDomNode &dataNode)
read internal state from node
QString mType
description of the kind if registration (manual, patient, landmark, coregistration etc) ...
virtual void removeNewerThan(const QDateTime &timestamp)
virtual ParentSpace getCurrentParentSpace()
A registration event and its transform.
virtual void clear()
reset all data loaded from xml
virtual void updateParentSpace(const QDateTime &oldTime, const ParentSpace &newParent)
bool operator==(const RegistrationTransform &lhs, const RegistrationTransform &rhs)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
virtual RegistrationTransform getCurrentRegistration() const
virtual std::vector< ParentSpace > getParentSpaces() const
virtual void parseXml(QDomNode &dataNode)
read internal state from node
virtual void parseXml(QDomNode &dataNode)
read internal state from node
virtual void addOrUpdateRegistration(const QDateTime &oldTime, const RegistrationTransform &newTransform)
virtual void addOrUpdateRegistration(const QDateTime &oldTime, const RegistrationTransform &newTransform)
virtual void setActiveTime(const QDateTime &timestamp)
virtual void addParentSpace(const ParentSpace &newParent)
virtual void addParentSpace(const QString &newParent)
void addXml(QDomNode &parentNode) const
write internal state to node
virtual void setRegistration(const Transform3D &transform)
A history of registration events.
Namespace for all CustusX production code.