NorMIT-nav  16.5
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 
35 //#include <QtXML>
36 #include <QDomElement>
37 #include "cxTime.h"
38 #include "cxTypeConversions.h"
39 
40 namespace cx
41 {
42 
43 // --------------------------------------------------------
44 RegistrationHistoryPtr RegistrationHistory::mNull;
45 // --------------------------------------------------------
46 
47 
51 {
52 public:
53  virtual void addXml(QDomNode& parentNode) const
54  {
55  }
56  virtual void parseXml(QDomNode& dataNode)
57  {
58  }
59 
61  {
62  }
63  virtual void setRegistration(const Transform3D& transform)
64  {
65  }
66  virtual void updateRegistration(const QDateTime& oldTime, const RegistrationTransform& newTransform)
67  {
68  }
69 
70  virtual void setParentSpace(const QString& newParent)
71  {
72  }
73  virtual void addParentSpace(const QString& newParent)
74  {
75  }
76  virtual void addParentSpace(const ParentSpace& newParent)
77  {
78  }
79  virtual void updateParentSpace(const QDateTime& oldTime, const ParentSpace& newParent)
80  {
81  }
82 
83  virtual std::vector<RegistrationTransform> getData() const
84  {
85  return std::vector<RegistrationTransform>();
86  }
87  virtual std::vector<ParentSpace> getParentSpaces() const
88  {
89  return std::vector<ParentSpace>();
90  }
91  virtual void removeNewerThan(const QDateTime& timestamp)
92  {
93  }
94  virtual void setActiveTime(const QDateTime& timestamp)
95  {
96  }
97  virtual QDateTime getActiveTime() const
98  {
99  return QDateTime();
100  }
102  {
103  return RegistrationTransform();
104  }
106  {
107  return ParentSpace();
108  }
109  virtual void clear()
110  {
111  }
112  virtual bool isNull() const
113  {
114  return true;
115  }
116 };
117 
118 //---------------------------------------------------------
119 //------- RegistrationTransform -------------------------
120 //---------------------------------------------------------
121 
123  mValue(Transform3D::Identity())
124 {
125 }
126 
127 RegistrationTransform::RegistrationTransform(const Transform3D& value, const QDateTime& timestamp, const QString& type)
128 {
129  mValue = value;
130  mTimestamp = timestamp;
131  mType = type;
132 }
133 
134 void RegistrationTransform::addXml(QDomNode& parentNode) const
135 {
136  QDomDocument doc = parentNode.ownerDocument();
137  QDomElement base = doc.createElement("registrationTransform");
138  parentNode.appendChild(base);
139 
140  base.setAttribute("timestamp", mTimestamp.toString(timestampSecondsFormat()));
141  base.setAttribute("type", mType);
142 
143  if (!mFixed.isEmpty())
144  base.setAttribute("fixed", mFixed);
145  if (!mMoving.isEmpty())
146  base.setAttribute("moving", mMoving);
147 
148  base.appendChild(doc.createTextNode("\n" + qstring_cast(mValue)));
149 }
150 
151 void RegistrationTransform::parseXml(QDomNode& dataNode)
152 {
153  if (dataNode.isNull())
154  return;
155 
156  QDomElement base = dataNode.toElement();
157 
158  mTimestamp = QDateTime::fromString(base.attribute("timestamp"), timestampSecondsFormat());
159  mType = base.attribute("type");
160  mValue = Transform3D::fromString(base.text());
161  mFixed = base.attribute("fixed");
162  mMoving = base.attribute("moving");
163 }
164 
166 {
167  return lhs.mTimestamp < rhs.mTimestamp;
168 }
169 
171 {
172  return similar(lhs.mValue, rhs.mValue, 1.0E-3) && (lhs.mTimestamp == rhs.mTimestamp) && (lhs.mType == rhs.mType);
173 }
174 
175 //---------------------------------------------------------
176 //------- RegistrationTransform -------------------------
177 //---------------------------------------------------------
178 
180 {
181 
182 }
183 
184 ParentSpace::ParentSpace(const QString& uid, const QDateTime& timestamp, const QString& type)
185 {
186  mValue = uid;
187  mTimestamp = timestamp;
188  mType = type;
189 }
190 
191 void ParentSpace::addXml(QDomNode& parentNode) const
192 {
193  QDomDocument doc = parentNode.ownerDocument();
194  QDomElement base = doc.createElement("parentFrame");
195  parentNode.appendChild(base);
196 
197  base.setAttribute("value", mValue);
198  base.setAttribute("timestamp", mTimestamp.toString(timestampSecondsFormat()));
199  base.setAttribute("type", mType);
200 }
201 
202 void ParentSpace::parseXml(QDomNode& dataNode)
203 {
204  if (dataNode.isNull())
205  return;
206 
207  QDomElement base = dataNode.toElement();
208 
209  mTimestamp = QDateTime::fromString(base.attribute("timestamp"), timestampSecondsFormat());
210  mType = base.attribute("type");
211  mValue = base.attribute("value");
212 }
213 
214 bool operator<(const ParentSpace& lhs, const ParentSpace& rhs)
215 {
216  return lhs.mTimestamp < rhs.mTimestamp;
217 }
218 
219 bool operator==(const ParentSpace& lhs, const ParentSpace& rhs)
220 {
221  return (lhs.mValue == rhs.mValue) && (lhs.mTimestamp == rhs.mTimestamp) && (lhs.mType == rhs.mType);
222 }
223 
224 //---------------------------------------------------------
225 //------- RegistrationHistory -------------------------
226 //---------------------------------------------------------
227 
229 {
230  if (!mNull)
231  mNull.reset(new RegistrationHistoryNull);
232  return mNull;
233 }
234 
235 void RegistrationHistory::addXml(QDomNode& parentNode) const
236 {
237  QDomDocument doc = parentNode.ownerDocument();
238  QDomElement base = doc.createElement("registrationHistory");
239  parentNode.appendChild(base);
240 
241  QDomElement currentTime = doc.createElement("currentTime");
242  currentTime.appendChild(doc.createTextNode(mCurrentTime.toString(timestampSecondsFormat())));
243  base.appendChild(currentTime);
244 
245  for (unsigned i = 0; i < mData.size(); ++i)
246  {
247  mData[i].addXml(base);
248  }
249  for (unsigned i = 0; i < mParentSpaces.size(); ++i)
250  {
251  mParentSpaces[i].addXml(base);
252  }
253 }
254 
255 void RegistrationHistory::parseXml(QDomNode& dataNode)
256 {
257  if (dataNode.isNull())
258  return;
259 
260  mData.clear();
261  QString currentTimeRaw = dataNode.namedItem("currentTime").toElement().text();
262  QDateTime currentTime = QDateTime::fromString(currentTimeRaw, timestampSecondsFormat());
263 
264  // iterate over all data elements
265  QDomElement currentElem = dataNode.firstChildElement("registrationTransform");
266  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("registrationTransform"))
267  {
269  transform.parseXml(currentElem);
270  mData.push_back(transform);
271  }
272 
273  // iterate over all data elements
274  currentElem = dataNode.firstChildElement("parentFrame");
275  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("parentFrame"))
276  {
278  transform.parseXml(currentElem);
279  mParentSpaces.push_back(transform);
280  }
281 
282  std::sort(mData.begin(), mData.end());
283  std::sort(mParentSpaces.begin(), mParentSpaces.end());
284  setActiveTime(currentTime); // update cache
285 }
286 
288 {
289  mData.clear();
290  mCurrentTime = QDateTime();
291  mTransformCache = RegistrationTransform();
292 }
293 
297 {
298  if (std::count(mData.begin(), mData.end(), transform)) // ignore if already present
299  return;
300 
301  mData.push_back(transform);
302  std::sort(mData.begin(), mData.end());
303  setActiveTime(QDateTime()); // reset to last registration when reregistering.
304 }
305 
309 void RegistrationHistory::updateRegistration(const QDateTime& oldTime, const RegistrationTransform& newTransform)
310 {
311  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
312  {
313  if ((iter->mTimestamp == oldTime)
314  && oldTime.isValid()
315  && (iter->mType == newTransform.mType))
316  {
317  mData.erase(iter);
318  break;
319  }
320  }
321  this->addRegistration(newTransform);
322 }
323 
328 {
329  bool changed = true;
330  if (similar(getCurrentRegistration().mValue, transform))
331  {
332  changed = false;
333  }
334  mData.clear();
335  this->addRegistration(RegistrationTransform(transform));
336  if (changed)
337  {
338  emit currentChanged();
339  }
340 }
341 
345 void RegistrationHistory::setParentSpace(const QString& newParent)
346 {
347  mParentSpaces.clear();
348  this->addParentSpace(ParentSpace(newParent));
349 }
350 
351 void RegistrationHistory::addParentSpace(const QString& newParent)
352 {
353  this->addParentSpace(ParentSpace(newParent, QDateTime::currentDateTime(), "Set Parent Frame"));
354 }
355 
357 {
358  if (std::count(mParentSpaces.begin(), mParentSpaces.end(), newParent)) // ignore if already present
359  return;
360 
361  mParentSpaces.push_back(newParent);
362  std::sort(mParentSpaces.begin(), mParentSpaces.end());
363  setActiveTime(QDateTime()); // reset to last registration when reregistering.
364 }
365 
366 void RegistrationHistory::updateParentSpace(const QDateTime& oldTime, const ParentSpace& newParent)
367 {
368  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
369  {
370  if (iter->mTimestamp != oldTime)
371  continue;
372  mParentSpaces.erase(iter);
373  break;
374  }
375  this->addParentSpace(newParent);
376 }
377 
379 {
380  return mParentSpaceCache;
381 }
382 
383 std::vector<RegistrationTransform> RegistrationHistory::getData() const
384 {
385  return mData;
386 }
387 
388 std::vector<ParentSpace> RegistrationHistory::getParentSpaces() const
389 {
390  return mParentSpaces;
391 }
392 
393 void RegistrationHistory::removeNewerThan(const QDateTime& timestamp)
394 {
395  if (!timestamp.isValid())
396  return;
397 
398  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end();)
399  {
400  if (iter->mTimestamp > timestamp)
401  {
402  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
403  << "): removed [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", " << iter->mType
404  << "]" << std::endl;
405  iter = mData.erase(iter);
406  }
407  else
408  {
409  ++iter;
410  }
411  }
412 
413  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end();)
414  {
415  if (iter->mTimestamp > timestamp)
416  {
417  std::cout << "RegistrationHistory::removeNewerThan(" << timestamp.toString(timestampSecondsFormatNice())
418  << "): removed parent frame [" << iter->mTimestamp.toString(timestampSecondsFormatNice()) << ", "
419  << iter->mType << "]" << std::endl;
420  iter = mParentSpaces.erase(iter);
421  }
422  else
423  {
424  ++iter;
425  }
426  }
427 
428  setActiveTime(QDateTime());
429 }
430 
431 void RegistrationHistory::setCache(const RegistrationTransform& val, const ParentSpace& parent,
432  const QDateTime& timestamp)
433 {
434  if ((mTransformCache == val) && (mParentSpaceCache == parent) && (mCurrentTime == timestamp))
435  return;
436 
437  mCurrentTime = timestamp;
438  mTransformCache = val;
439  mParentSpaceCache = parent;
440 
441  emit currentChanged();
442 }
443 
447 void RegistrationHistory::setActiveTime(const QDateTime& timestamp)
448 {
450  ParentSpace parent;
451  // set to specified time
452  if (timestamp.isValid())
453  {
454  for (std::vector<RegistrationTransform>::iterator iter = mData.begin(); iter != mData.end(); ++iter)
455  {
456  if (iter->mTimestamp <= timestamp)
457  val = *iter;
458  }
459  for (std::vector<ParentSpace>::iterator iter = mParentSpaces.begin(); iter != mParentSpaces.end(); ++iter)
460  {
461  if (iter->mTimestamp <= timestamp)
462  parent = *iter;
463  }
464  }
465  else
466  {
467  if (!mData.empty())
468  val = mData.back();
469  if (!mParentSpaces.empty())
470  parent = mParentSpaces.back();
471  }
472 
473  setCache(val, parent, timestamp);
474 }
475 
477 {
478  return mCurrentTime;
479 }
480 
482 {
483  return mTransformCache;
484 }
485 
486 } // end namespace cx
487 
QString qstring_cast(const T &val)
QString mValue
parent frame uid
virtual void setRegistration(const Transform3D &transform)
bool operator<(const Landmark &lhs, const Landmark &rhs)
Definition: cxLandmark.cpp:94
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:57
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.
QString timestampSecondsFormatNice()
Definition: cxTime.cpp:47
virtual void updateParentSpace(const QDateTime &oldTime, const ParentSpace &newParent)
virtual void setActiveTime(const QDateTime &timestamp)
virtual QDateTime getActiveTime() const
QString timestampSecondsFormat()
Definition: cxTime.cpp:39
virtual void clear()
reset all data loaded from xml
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
virtual void addXml(QDomNode &parentNode) const
write internal state to node
virtual std::vector< ParentSpace > getParentSpaces() const
virtual void updateRegistration(const QDateTime &oldTime, const RegistrationTransform &newTransform)
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 void addRegistration(const RegistrationTransform &transform)
virtual void addRegistration(const RegistrationTransform &transform)
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)
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 setActiveTime(const QDateTime &timestamp)
virtual void updateRegistration(const QDateTime &oldTime, const RegistrationTransform &newTransform)
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.