CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxICPRegistrationBaseWidget.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 =========================================================================*/
12 
13 #include <QPushButton>
14 #include <QLabel>
15 #include <QSpinBox>
16 #include <QCheckBox>
17 #include <QGroupBox>
18 #include <vtkCellArray.h>
19 #include "cxTypeConversions.h"
20 #include "cxLogger.h"
21 #include "cxTimedAlgorithm.h"
25 #include "cxMesh.h"
26 #include "cxView.h"
27 #include "cxGeometricRep.h"
28 #include "cxGraphicalPrimitives.h"
29 #include "cxRegistrationService.h"
30 #include "cxViewService.h"
31 #include "cxPatientModelService.h"
32 #include "cxICPWidget.h"
33 #include "cxMeshInView.h"
35 #include "cxSpaceProvider.h"
36 #include "cxSpaceListener.h"
37 #include "cxProfile.h"
38 
39 namespace cx
40 {
41 
42 ICPRegistrationBaseWidget::ICPRegistrationBaseWidget(RegServicesPtr services, QWidget* parent, QString uid, QString name) :
43  RegistrationBaseWidget(services, parent, uid, name)
44 {
45  this->setLayout(new QVBoxLayout); // we need something, otherwise the widget might not be painted at all.
46 }
47 
49 {
50 }
51 
53 {
54  if (!mRegistrator)
55  {
56  this->initialize();
57  this->setup();
58  }
59 
60  this->initializeRegistrator();
61 
63  this->updateDifferenceLines();
64  mICPWidget->setRMS(mRegistrator->getResultMetric());
65 }
66 
67 void ICPRegistrationBaseWidget::initialize()
68 {
69  delete this->layout(); // dummy layout from construct
70 
71  mRegistrator.reset(new SeansVesselReg());
72  mOptions = profile()->getXmlSettings().descend("uid");
73 
74  this->initializeProperties();
75 
76  mICPWidget = new ICPWidget(this);
77  mICPWidget->setSettings(this->getAllProperties());
79 
81  connect(mObscuredListener.get(), SIGNAL(obscured(bool)), this, SLOT(obscuredSlot(bool)));
82 }
83 
84 
85 void ICPRegistrationBaseWidget::initializeProperties()
86 {
87  mAutoLTS = BoolProperty::initialize("autoLTS","Auto LTS",
88  "Ignore LTS, instead attempt to find optimal value",
91 
92  mLTSRatio = DoubleProperty::initialize("LTSRatio", "LTS Ratio",
93  "Fraction of points in the lesser point set to use during each iteration.",
94  80, DoubleRange(20,100,1), 0, mOptions.getElement());
96 
97  mNumberOfIterations = DoubleProperty::initialize("Iterations", "Iterations",
98  "Number of iterations",
99  500, DoubleRange(1,1000,1), 0, mOptions.getElement());
100  connect(mNumberOfIterations.get(), &DoubleProperty::changed, this, &ICPRegistrationBaseWidget::onSettingsChanged);
101 
102  mStopThreshold = DoubleProperty::initialize("StopThreshold", "Stop Threshold",
103  "Differential RMS stop threshold, between iterations",
104  0.001, DoubleRange(0.0001,1,0.0001), 4, mOptions.getElement());
105  connect(mStopThreshold.get(), &DoubleProperty::changed, this, &ICPRegistrationBaseWidget::onSettingsChanged);
106 
107  mMaxTime = DoubleProperty::initialize("MaxTime", "Max Time",
108  "Maximum time spent iterating, in seconds",
109  60, DoubleRange(1,300,1), 0, mOptions.getElement());
111 
112  mMargin = DoubleProperty::initialize("Margin", "Margin",
113  "Data outside a bounding box defined by the intersection\n"
114  "of the fixed/moving by a margin are cropped.",
115  40, DoubleRange(10,100,1), 0, mOptions.getElement());
117 
118  mLinear = BoolProperty::initialize("linear","Linear",
119  "Use only linear iteration",
120  true, mOptions.getElement());
122 
123  mDisplayProgress = BoolProperty::initialize("progress","Display Progress",
124  "Display metric and difference lines between point sets",
125  true, mOptions.getElement());
126  connect(mDisplayProgress.get(), &DoubleProperty::changed, this, &ICPRegistrationBaseWidget::onDisplayProgressChanged);
127 
128  mOneStep = BoolProperty::initialize("onestep","One Step",
129  "Registration is done one iteration at a time.",
130  false); // note: do not store the value in this case: always reset to default.
131 }
132 
133 std::vector<PropertyPtr> ICPRegistrationBaseWidget::getAllProperties()
134 {
135  std::vector<PropertyPtr> properties;
136  properties.push_back(mLTSRatio);
137  properties.push_back(mAutoLTS);
138  properties.push_back(mMargin);
139  properties.push_back(mLinear);
140  properties.push_back(mDisplayProgress);
141  properties.push_back(mOneStep);
142  properties.push_back(mNumberOfIterations);
143  properties.push_back(mStopThreshold);
144  properties.push_back(mMaxTime);
145  return properties;
146 }
147 
148 void ICPRegistrationBaseWidget::obscuredSlot(bool obscured)
149 {
150  if (obscured)
151  {
152  mMeshInView.reset();
153  }
154  else
155  {
156  this->onSettingsChanged();
157  this->onShown();
158  }
159 }
160 
162 {
163  if (mObscuredListener->isObscured())
164  return;
165 
166  this->setModified();
167 // this->initializeRegistrator();
168 
169 // mICPWidget->enableRegistration(mRegistrator->isValid());
170 // this->updateDifferenceLines();
171 // mICPWidget->setRMS(mRegistrator->getResultMetric());
172 }
173 
175 {
176  if (mObscuredListener->isObscured())
177  return;
178  mRegistrator->mt_auto_lts = mAutoLTS->getValue();
179  mRegistrator->mt_ltsRatio = mLTSRatio->getValue();
180  mRegistrator->mt_doOnlyLinear = mLinear->getValue();
181  mRegistrator->margin = mMargin->getValue();
182  mRegistrator->mt_maximumNumberOfIterations = mNumberOfIterations->getValue();
183  mRegistrator->mt_distanceDeltaStopThreshold = mStopThreshold->getValue();
184  mRegistrator->mt_maximumDurationSeconds = mMaxTime->getValue();
185 }
186 
188 {
189 // int lts_ratio = mLTSRatioSpinBox->value();
190 // double stop_delta = 0.001; //TODO, add user interface
191 // double lambda = 0; //TODO, add user interface
192 // double sigma = 1.0; //TODO, add user interface
193 // bool lin_flag = mLinearCheckBox->isChecked(); //TODO, add user interface
194 // int sample = 1; //TODO, add user interface
195 // int single_point_thre = 1; //TODO, add user interface
196 // bool verbose = 1; //TODO, add user interface
197 
198  mRegistrator->notifyPreRegistrationWarnings();
199 
200  if (mRegistrator->mt_auto_lts)
201  {
202  reportDebug("Using automatic lts_ratio");
203  }
204  else
205  {
206  reportDebug("Using lts_ratio: " + qstring_cast(mRegistrator->mt_ltsRatio));
207  }
208 
209  bool success = false;
210  if (mOneStep->getValue())
211  success = mRegistrator->performOneRegistration();
212  else
213  success = mRegistrator->execute();
214 
215  if (!success)
216  {
217  reportWarning("ICP registration failed.");
218  return;
219  }
220 
221  Transform3D linearTransform = mRegistrator->getLinearResult();
222 
223  std::cout << "v2v linear result:\n" << linearTransform << std::endl;
224  //std::cout << "v2v inverted linear result:\n" << linearTransform.inverse() << std::endl;
225 
226  if ((std::isnan)(linearTransform(0,0)))
227  {
228  reportWarning("ICP registration failed.");
229  return;
230  }
231 
232  mRegistrator->checkQuality(linearTransform);
233 
234  // The registration is performed in space r. Thus, given an old data position rMd, we find the
235  // new one as rM'd = Q * rMd, where Q is the inverted registration output.
236  // Delta is thus equal to Q:
237  Transform3D delta = linearTransform.inv();
238  //std::cout << "delta:\n" << delta << std::endl;
239 
240  this->applyRegistration(delta);
241 }
242 
243 
244 void ICPRegistrationBaseWidget::updateDifferenceLines()
245 {
246  if (!mMeshInView)
247  mMeshInView.reset(new MeshInView(mServices->view()));
248 
249  bool show = mDisplayProgress->getValue() && mRegistrator->isValid();
250  if (show)
251  mMeshInView->show(mRegistrator->getDifferenceLines());
252  else
253  mMeshInView->hide();
254 }
255 
256 void ICPRegistrationBaseWidget::onDisplayProgressChanged()
257 {
258  this->updateDifferenceLines();
259 }
260 
261 
262 } // namespace cx
QString qstring_cast(const T &val)
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
void setSettings(std::vector< PropertyPtr > properties)
Definition: cxICPWidget.cpp:75
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:32
virtual void initializeRegistrator()=0
QDomElement getElement()
return the current element
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
void requestRegister()
boost::shared_ptr< class WidgetObscuredListener > mObscuredListener
virtual void applyRegistration(Transform3D delta)=0
boost::shared_ptr< class RegServices > RegServicesPtr
Definition: cxRegServices.h:20
ICPRegistrationBaseWidget(RegServicesPtr services, QWidget *parent, QString uid, QString name)
void changed()
emit when the underlying data value is changed: The user interface will be updated.
void setRMS(double val)
Definition: cxICPWidget.cpp:93
void enableRegistration(bool on)
Definition: cxICPWidget.cpp:84
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
void reportDebug(QString msg)
Definition: cxLogger.cpp:68
Namespace for all CustusX production code.