CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxRouteToTargetFilterService.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 
13 
14 #include <ctkPluginContext.h>
15 #include <QDir>
16 
17 #include "cxAlgorithmHelpers.h"
19 
20 #include "cxUtilHelpers.h"
22 #include "cxStringProperty.h"
23 #include "cxDoubleProperty.h"
24 #include "cxBoolProperty.h"
25 #include "cxTypeConversions.h"
26 #include "cxImage.h"
27 
28 #include "cxRouteToTarget.h"
29 #include "cxPatientModelService.h"
30 #include "cxPointMetric.h"
31 #include "cxVisServices.h"
34 #include "cxViewService.h"
35 #include "cxLog.h"
36 
37 #include <vtkPolyData.h>
38 
39 
40 namespace cx
41 {
42 
43 RouteToTargetFilter::RouteToTargetFilter(VisServicesPtr services, bool createRouteInformationFile) :
44  FilterImpl(services),
45  mGenerateFileWithRouteInformation(createRouteInformationFile),
46  mSmoothing(true)
47 {
48 }
49 
51 {
52  return "Route to target";
53 }
54 
56 {
57  return "routetotarget_filter";
58 }
59 
61 {
62  return "<html>"
63  "<h3>Route to target.</h3>"
64  "<p>Calculates the route to a selected target in navigated bronchocopy. "
65  "The route starts at the top of trachea and ends at the most adjacent airway centerline"
66  "from the target.</p>"
67  "</html>";
68 }
69 
71 {
72  return "_rtt_cl";
73 }
74 
76 {
77  return "_ext";
78 }
79 
81 {
82  return "_vessel";
83 }
84 
86 {
87  return "_AirwaysModel";
88 }
89 
91 {
92  return "_AirwaysAndVessel_RTT";
93 }
94 
95 
97 {
98  mOptionsAdapters.push_back(this->getBloodVesselOption(mOptions));
99 }
100 
102 {
103  StringPropertySelectMeshPtr centerline;
104  centerline = StringPropertySelectMesh::New(mServices->patient());
105  centerline->setValueName("Airways centerline");
106  centerline->setHelp("Select airways centerline");
107  mInputTypes.push_back(centerline);
108 
110  targetPoint = StringPropertySelectPointMetric::New(mServices->patient());
111  targetPoint->setValueName("Target point");
112  targetPoint->setHelp("Select target point metric");
113  mInputTypes.push_back(targetPoint);
114 
115  StringPropertySelectMeshPtr bloodVesselCenterline;
116  bloodVesselCenterline = StringPropertySelectMesh::New(mServices->patient());
117  bloodVesselCenterline->setValueName("Blood vessel centerline");
118  bloodVesselCenterline->setHelp("Select blood vessel centerline");
119  mInputTypes.push_back(bloodVesselCenterline);
120 
121  SelectDataStringPropertyBasePtr bloodVesselSegmentationVolume;
122  bloodVesselSegmentationVolume = StringPropertySelectImage::New(mServices->patient());
123  bloodVesselSegmentationVolume->setValueName("Blood vessel segmentation volume");
124  bloodVesselSegmentationVolume->setHelp("Select blood vessel segmentation volume");
125  mInputTypes.push_back(bloodVesselSegmentationVolume);
126 
127 }
128 
129 
131 {
132  StringPropertySelectMeshPtr tempRTTMeshStringAdapter;
133  tempRTTMeshStringAdapter = StringPropertySelectMesh::New(mServices->patient());
134  tempRTTMeshStringAdapter->setValueName("Route to target (mesh)");
135  tempRTTMeshStringAdapter->setHelp("Generated route to target mesh (vtk-format).");
136  mOutputTypes.push_back(tempRTTMeshStringAdapter);
137 
138  StringPropertySelectMeshPtr tempRTTEXTMeshStringAdapter;
139  tempRTTEXTMeshStringAdapter = StringPropertySelectMesh::New(mServices->patient());
140  tempRTTEXTMeshStringAdapter->setValueName("Route to target extended (mesh)");
141  tempRTTEXTMeshStringAdapter->setHelp("Generated route to target extended mesh (vtk-format).");
142  mOutputTypes.push_back(tempRTTEXTMeshStringAdapter);
143 
144  StringPropertySelectMeshPtr tempRTTVesselMeshStringAdapter;
145  tempRTTVesselMeshStringAdapter = StringPropertySelectMesh::New(mServices->patient());
146  tempRTTVesselMeshStringAdapter->setValueName("Route to target along blood vessels (mesh)");
147  tempRTTVesselMeshStringAdapter->setHelp("Generated route to target along blood vessels mesh (vtk-format).");
148  mOutputTypes.push_back(tempRTTVesselMeshStringAdapter);
149 
150  StringPropertySelectMeshPtr tempRTTVesselAndAirwayRTTMeshStringAdapter;
151  tempRTTVesselAndAirwayRTTMeshStringAdapter = StringPropertySelectMesh::New(mServices->patient());
152  tempRTTVesselAndAirwayRTTMeshStringAdapter->setValueName("Connected route - airways and vessels (mesh)");
153  tempRTTVesselAndAirwayRTTMeshStringAdapter->setHelp("Connected route to target - airways and blood vessels mesh (vtk-format).");
154  mOutputTypes.push_back(tempRTTVesselAndAirwayRTTMeshStringAdapter);
155 
156  StringPropertySelectMeshPtr tempAirwaysModelMeshStringAdapter;
157  tempAirwaysModelMeshStringAdapter = StringPropertySelectMesh::New(mServices->patient());
158  tempAirwaysModelMeshStringAdapter->setValueName("Airways along blood vessels surface model (mesh)");
159  tempAirwaysModelMeshStringAdapter->setHelp("Generated airways surface model mesh (vtk-format).");
160  mOutputTypes.push_back(tempAirwaysModelMeshStringAdapter);
161 }
162 
163 
165 {
166  mRouteToTarget.reset(new RouteToTarget());
167 
168  MeshPtr mesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[0])->getMesh();
169  if (!mesh)
170  return false;
171 
172  PointMetricPtr targetPoint = boost::dynamic_pointer_cast<StringPropertySelectPointMetric>(mInputTypes[1])->getPointMetric();
173  if (!targetPoint)
174  return false;
175 
176  mRouteToTarget->setSmoothing(mSmoothing);
177 
178  if(mReprocessCenterline || !mBranchListPtr)
179  {
180  mRouteToTarget->processCenterline(mesh);
181  mBranchListPtr = mRouteToTarget->getBranchList();
182  }
183  else
184  {
185  mRouteToTarget->setBranchList(mBranchListPtr);
186  }
187 
188  //note: mOutput is in reference space
189  mOutput = mRouteToTarget->findRouteToTarget(targetPoint);
190 
191  if(mOutput->GetNumberOfPoints() < 1)
192  return false;
193 
194  mExtendedRoute = mRouteToTarget->findExtendedRoute(targetPoint);
195 
196  if (mGenerateFileWithRouteInformation)
197  mRouteToTarget->addRouteInformationToFile(mServices);
198 
199  if (getBloodVesselOption(mOptions)->getValue())
200  {
201  ImagePtr bloodVesselVolume = this->getCopiedInputImage(3);
202 
203  MeshPtr bloodVesselCenterline = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[2])->getMesh();
204  if (bloodVesselCenterline)
205  {
206  if (bloodVesselVolume)
207  mRouteToTarget->setBloodVesselVolume(bloodVesselVolume);
208 
209  mBloodVesselRoute = mRouteToTarget->findRouteToTargetAlongBloodVesselCenterlines( bloodVesselCenterline, targetPoint);
210  mAirwaysFromBloodVessel = mRouteToTarget->generateAirwaysFromBloodVesselCenterlines();
211  }
212 
213  mAirwayAndBloodVesselRoute = mRouteToTarget->getConnectedAirwayAndBloodVesselRoute();
214  }
215  return true;
216 }
217 
219 {
220 
221  MeshPtr inputMesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[0])->getMesh();
222  if (!inputMesh)
223  return false;
224 
225  PointMetricPtr targetPoint = boost::dynamic_pointer_cast<StringPropertySelectPointMetric>(mInputTypes[1])->getPointMetric();
226  if (!targetPoint)
227  return false;
228 
229  QString uidOutputCenterline = inputMesh->getName() + "_" + targetPoint->getName() + RouteToTargetFilter::getNameSuffix();
230  QString nameOutputCenterline = inputMesh->getName() + "_" + targetPoint->getName() + RouteToTargetFilter::getNameSuffix();
231 
232  MeshPtr outputCenterline = patientService()->createSpecificData<Mesh>(uidOutputCenterline, nameOutputCenterline);
233  outputCenterline->setVtkPolyData(mOutput);
234  outputCenterline->getProperties().mLineWidth->setValue(5); //Setting thicker line for RTT
235  patientService()->insertData(outputCenterline, true);
236 
237  QString uidCenterlineExt = outputCenterline->getUid() + RouteToTargetFilter::getNameSuffixExtension();
238  QString nameCenterlineExt = outputCenterline->getName() + RouteToTargetFilter::getNameSuffixExtension();
239  MeshPtr outputCenterlineExt = patientService()->createSpecificData<Mesh>(uidCenterlineExt, nameCenterlineExt);
240  outputCenterlineExt->setVtkPolyData(mExtendedRoute);
241  outputCenterlineExt->setColor(QColor(0, 0, 255, 255));
242  outputCenterlineExt->getProperties().mLineWidth->setValue(5); //Setting thicker line for RTT
243  patientService()->insertData(outputCenterlineExt, true);
244 
245  //note: mOutput and outputCenterline is in reference(r) space
246 
247 
248  //Meshes are expected to be in data(d) space
249  outputCenterline->get_rMd_History()->setParentSpace(inputMesh->getUid());
250  outputCenterlineExt->get_rMd_History()->setParentSpace(inputMesh->getUid());
251 
252  //mServices->view()->autoShowData(outputCenterlineExt);
253  //mServices->view()->autoShowData(outputCenterline);
254 
255  if(mOutputTypes.size() > 0)
256  mOutputTypes[0]->setValue(outputCenterline->getUid());
257  if(mOutputTypes.size() > 1)
258  mOutputTypes[1]->setValue(outputCenterlineExt->getUid());
259 
260  MeshPtr bloodVesselCenterlineMesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[2])->getMesh();
261  if(mBloodVesselRoute && bloodVesselCenterlineMesh && getBloodVesselOption(mOptions)->getValue())
263 
264 // //Create Ceetron route-to-target file
265 // QString CeetronPath = mServices->patient()->getActivePatientFolder() + "/Images/MarianaRTT/";
266 // QDir CeetronDirectory(CeetronPath);
267 // if (!CeetronDirectory.exists()) // Creating MarianaRTT folder if it does not exist
268 // CeetronDirectory.mkpath(CeetronPath);
269 // QString filePathCeetron = CeetronPath + outputCenterline->getUid() + ".txt";
270 // mRouteToTarget->makeMarianaCenterlineFile(filePathCeetron);
271 
272  return true;
273 }
274 
276 {
277  MeshPtr inputMesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[0])->getMesh();
278  PointMetricPtr targetPoint = boost::dynamic_pointer_cast<StringPropertySelectPointMetric>(mInputTypes[1])->getPointMetric();
279  QString uidOutputCenterline = inputMesh->getName() + "_" + targetPoint->getName() + RouteToTargetFilter::getNameSuffix();
280  QString nameOutputCenterline = inputMesh->getName() + "_" + targetPoint->getName() + RouteToTargetFilter::getNameSuffix();
281  MeshPtr outputCenterline = patientService()->createSpecificData<Mesh>(uidOutputCenterline, nameOutputCenterline);
282 
283  MeshPtr bloodVesselCenterlineMesh = boost::dynamic_pointer_cast<StringPropertySelectMesh>(mInputTypes[2])->getMesh();
284 
285  QString uidCenterlineBV = outputCenterline->getUid() + RouteToTargetFilter::getNameSuffixBloodVessel();
286  QString nameCenterlineBV = outputCenterline->getName() + RouteToTargetFilter::getNameSuffixBloodVessel();
287  MeshPtr outputCenterlineBV = patientService()->createSpecificData<Mesh>(uidCenterlineBV, nameCenterlineBV);
288  outputCenterlineBV->setVtkPolyData(mBloodVesselRoute);
289  outputCenterlineBV->setColor(QColor(0, 255, 0, 255));
290  patientService()->insertData(outputCenterlineBV);
291 
292  outputCenterlineBV->get_rMd_History()->setParentSpace(inputMesh->getUid());
293 
294  if(mOutputTypes.size() > 2)
295  mOutputTypes[2]->setValue(outputCenterlineBV->getUid());
296 
297  if(mAirwaysFromBloodVessel)
298  {
299  QString uidSurfaceModel = uidCenterlineBV + RouteToTargetFilter::getNameSuffixAirwayModel();
300  QString nameSurfaceModel = nameCenterlineBV + RouteToTargetFilter::getNameSuffixAirwayModel();
301 
302  MeshPtr outputMesh = patientService()->createSpecificData<Mesh>(uidSurfaceModel, nameSurfaceModel);
303  outputMesh->setVtkPolyData(mAirwaysFromBloodVessel);
304  outputMesh->setColor(QColor(192, 253, 246, 255));
305  patientService()->insertData(outputMesh);
306 
307  //Meshes are expected to be in data(d) space
308  outputMesh->get_rMd_History()->setParentSpace(inputMesh->getUid());
309 
310  if(mOutputTypes.size() > 4)
311  mOutputTypes[4]->setValue(outputMesh->getUid());
312 
313  }
314 
315  QString uidMergedCenterline = outputCenterline->getUid() + RouteToTargetFilter::getNameSuffixAirwayAndVesselRTT();
316  QString nameMergedCenterline = outputCenterline->getName() + RouteToTargetFilter::getNameSuffixAirwayAndVesselRTT();
317  MeshPtr outputMergedCenterline = patientService()->createSpecificData<Mesh>(uidMergedCenterline, nameMergedCenterline);
318  outputMergedCenterline->setVtkPolyData(mAirwayAndBloodVesselRoute);
319  outputMergedCenterline->setColor(QColor(0, 255, 0, 255));
320  outputMergedCenterline->getProperties().mLineWidth->setValue(5); //Setting thicker line for RTT
321  patientService()->insertData(outputMergedCenterline);
322 
323  outputMergedCenterline->get_rMd_History()->setParentSpace(inputMesh->getUid());
324 
325  if(mOutputTypes.size() >3)
326  mOutputTypes[3]->setValue(outputMergedCenterline->getUid());
327 
328  return true;
329 
330 }
331 
333 {
334  mSmoothing = smoothing; // default true
335 }
336 
337 std::vector< Eigen::Vector3d > RouteToTargetFilter::getRoutePositions(bool extendedRoute)
338 {
339  return mRouteToTarget->getRoutePositions(extendedRoute);
340 }
341 
343 {
344  return mRouteToTarget->getRouteBranches();
345 }
346 
348 {
349  return mRouteToTarget->getCameraRotation();
350 }
351 
353 {
354  return mRouteToTarget->getBranchingIndex();
355 }
356 
358 {
359  return mBranchListPtr;
360 }
361 
363 {
364  mBranchListPtr = branchList;
365 }
366 
368 {
369  mReprocessCenterline = reprocess;
370 }
371 
372 BoolPropertyPtr RouteToTargetFilter::getBloodVesselOption(QDomElement root)
373 {
374  BoolPropertyPtr retval =
375  BoolProperty::initialize("Use blood vessels to find RTT beyond airways",
376  "",
377  "Selecting this option to use blood vessels to find RTT beyond airways",
378  false, root);
379  return retval;
380 
381 }
382 
383 
384 } // namespace cx
385 
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
std::vector< SelectDataStringPropertyBasePtr > mInputTypes
Definition: cxFilterImpl.h:73
A mesh data set.
Definition: cxMesh.h:45
std::vector< Eigen::Vector3d > getRoutePositions(bool extendedRoute=true)
boost::shared_ptr< class BranchList > BranchListPtr
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
void setSmoothing(bool smoothing=true)
std::vector< PropertyPtr > mOptionsAdapters
Definition: cxFilterImpl.h:75
VisServicesPtr mServices
Definition: cxFilterImpl.h:82
boost::shared_ptr< class SelectDataStringPropertyBase > SelectDataStringPropertyBasePtr
PatientModelServicePtr patientService()
void setVtkPolyData(const vtkPolyDataPtr &polyData)
Definition: cxMesh.cpp:92
std::vector< BranchPtr > getRouteBranches()
ImagePtr getCopiedInputImage(int index=0)
QDomElement mOptions
Definition: cxFilterImpl.h:76
std::vector< SelectDataStringPropertyBasePtr > mOutputTypes
Definition: cxFilterImpl.h:74
static StringPropertySelectPointMetricPtr New(PatientModelServicePtr patientModelService)
std::vector< double > getCameraRotation()
static StringPropertySelectMeshPtr New(PatientModelServicePtr patientModelService)
boost::shared_ptr< class StringPropertySelectPointMetric > StringPropertySelectPointMetricPtr
static StringPropertySelectImagePtr New(PatientModelServicePtr patientModelService)
void setBranchList(BranchListPtr branchList)
boost::shared_ptr< class BoolProperty > BoolPropertyPtr
boost::shared_ptr< class Mesh > MeshPtr
RouteToTargetFilter(VisServicesPtr services, bool createRouteInformationFile=false)
boost::shared_ptr< class StringPropertySelectMesh > StringPropertySelectMeshPtr
Namespace for all CustusX production code.
boost::shared_ptr< class PointMetric > PointMetricPtr