CustusX  18.04
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  this->blockSignals(silent);
289  setActiveTime(QDateTime()); // reset to last registration when reregistering.
290  this->blockSignals(false);
291 }
292 
299 void RegistrationHistory::addOrUpdateRegistration(const QDateTime& oldTime, const RegistrationTransform& newTransform)
300 {
301  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
302  {
303  if ((iter->mTimestamp == oldTime)
304  && oldTime.isValid()
305  && iter->mTemp)
306  {
307  mData.erase(iter);
308  break;
309  }
310  }
311  this->addRegistrationInternal(newTransform);
312 }
313 
318 {
319  bool changed = true;
320  if (similar(getCurrentRegistration().mValue, transform))
321  {
322  changed = false;
323  }
324  mData.clear();
325  this->addRegistrationInternal(RegistrationTransform(transform));
326  if (changed)
327  {
328  emit currentChanged();
329  }
330 }
331 
335 void RegistrationHistory::setParentSpace(const QString& newParent)
336 {
337  mParentSpaces.clear();
338  this->addParentSpace(ParentSpace(newParent));
339 }
340 
341 void RegistrationHistory::addParentSpace(const QString& newParent)
342 {
343  this->addParentSpace(ParentSpace(newParent, QDateTime::currentDateTime(), "Set Parent Frame"));
344 }
345 
347 {
348  for (int i = 0; i < mParentSpaces.size(); ++i)
349  {
350  if(mParentSpaces[i].mUid == newParent.mUid)
351  return;// ignore if already present
352  }
353 
354  mParentSpaces.push_back(newParent);
355  std::sort(mParentSpaces.begin(), mParentSpaces.end());
356  setActiveTime(QDateTime()); // reset to last registration when reregistering.
357 }
358 
359 void RegistrationHistory::updateParentSpace(const QDateTime& oldTime, const ParentSpace& newParent)
360 {
361  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
362  {
363  if (iter->mTimestamp != oldTime)
364  continue;
365  mParentSpaces.erase(iter);
366  break;
367  }
368  this->addParentSpace(newParent);
369 }
370 
372 {
373  return mParentSpaceCache;
374 }
375 
376 std::vector<RegistrationTransform> RegistrationHistory::getData() const
377 {
378  return mData;
379 }
380 
381 std::vector<ParentSpace> RegistrationHistory::getParentSpaces() const
382 {
383  return mParentSpaces;
384 }
385 
386 void RegistrationHistory::removeNewerThan(const QDateTime& timestamp)
387 {
388  if (!timestamp.isValid())
389  return;
390 
391  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end();)
392  {
393  if (iter->mTimestamp > timestamp)
394  {
395  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
396  << "): removed [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", " << iter->mType
397  << "]" << std::endl;
398  iter = mData.erase(iter);
399  }
400  else
401  {
402  ++iter;
403  }
404  }
405 
406  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end();)
407  {
408  if (iter->mTimestamp > timestamp)
409  {
410  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
411  << "): removed parent frame [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", "
412  << iter->mType << "]" << std::endl;
413  iter = mParentSpaces.erase(iter);
414  }
415  else
416  {
417  ++iter;
418  }
419  }
420 
421  setActiveTime(QDateTime());
422 }
423 
424 void RegistrationHistory::setCache(const RegistrationTransform& val, const ParentSpace& parent,
425  const QDateTime& timestamp)
426 {
427  if ((mTransformCache == val) && (mParentSpaceCache == parent) && (mCurrentTime == timestamp))
428  return;
429 
430  mCurrentTime = timestamp;
431  mTransformCache = val;
432  mParentSpaceCache = parent;
433 
434  emit currentChanged();
435 }
436 
440 void RegistrationHistory::setActiveTime(const QDateTime& timestamp)
441 {
443  ParentSpace parent;
444  // set to specified time
445  if (timestamp.isValid())
446  {
447  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
448  {
449  if (iter->mTimestamp <= timestamp)
450  val = *iter;
451  }
452  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
453  {
454  if (iter->mTimestamp <= timestamp)
455  parent = *iter;
456  }
457  }
458  else
459  {
460  if (!mData.empty())
461  val = mData.back();
462  if (!mParentSpaces.empty())
463  parent = mParentSpaces.back();
464  }
465 
466  setCache(val, parent, timestamp);
467 }
468 
470 {
471  return mCurrentTime;
472 }
473 
475 {
476  return mTransformCache;
477 }
478 
479 } // end namespace cx
480 
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.