4 #include <vtkPolyData.h> 8 #include <vtkCellArray.h> 9 #include "vtkCardinalSpline.h" 13 #include <QTextStream> 14 #include <QJsonObject> 44 int N = centerline_r->GetNumberOfPoints();
45 Eigen::MatrixXd CLpoints(3,N);
46 for(vtkIdType i = 0; i < N; i++)
49 centerline_r->GetPoint(i,p);
50 Eigen::Vector3d position;
51 position(0) = p[0]; position(1) = p[1]; position(2) = p[2];
52 CLpoints.block(0 , i , 3 , 1) = position;
60 mBranchListPtr->deleteAllBranches();
62 vtkPolyDataPtr centerline_r = mesh->getTransformedPolyDataCopy(mesh->get_rMd());
66 mBranchListPtr->findBranchesInCenterline(CLpoints_r);
68 mBranchListPtr->calculateOrientations();
69 mBranchListPtr->smoothOrientations();
72 std::cout <<
"Number of branches in CT centerline: " << mBranchListPtr->getBranches().size() << std::endl;
78 double minDistance = 100000;
79 int minDistancePositionIndex;
81 std::vector<BranchPtr> branches = mBranchListPtr->getBranches();
82 for (
int i = 0; i < branches.size(); i++)
84 Eigen::MatrixXd positions = branches[i]->getPositions();
85 for (
int j = 0; j < positions.cols(); j++)
87 double D =
findDistance(positions.col(j), targetCoordinate_r);
91 minDistanceBranch = branches[i];
92 minDistancePositionIndex = j;
97 mProjectedBranchPtr = minDistanceBranch;
98 mProjectedIndex = minDistancePositionIndex;
104 mRoutePositions.clear();
117 if (!searchBranchPtr)
120 std::vector< Eigen::Vector3d > positions = smoothBranch(searchBranchPtr, startIndex, searchBranchPtr->getPositions().col(startIndex));
123 for (
int i = 0; i<=startIndex && i<positions.size(); i++)
124 mRoutePositions.push_back(positions[i]);
126 mBranchingIndex.push_back(mRoutePositions.size()-1);
128 BranchPtr parentBranchPtr = searchBranchPtr->getParentBranch();
130 searchBranchUp(parentBranchPtr, parentBranchPtr->getPositions().cols()-1);
136 mTargetPosition = targetPoint->getCoordinate();
148 mTargetPosition = targetPoint->getCoordinate();
149 double extentionPointIncrement = 0.25;
150 mExtendedRoutePositions.clear();
151 mExtendedRoutePositions = mRoutePositions;
152 if(mRoutePositions.size() > 0)
154 double extentionDistance =
findDistance(mRoutePositions.front(),mTargetPosition);
155 Eigen::Vector3d extentionVectorNormalized = ( mTargetPosition - mRoutePositions.front() ) / extentionDistance;
156 int numberOfextentionPoints = int(extentionDistance / extentionPointIncrement);
157 Eigen::Vector3d extentionPointIncrementVector = extentionVectorNormalized * extentionDistance / numberOfextentionPoints;
159 for (
int i = 1; i<= numberOfextentionPoints; i++)
161 mExtendedRoutePositions.insert(mExtendedRoutePositions.begin(), mRoutePositions.front() + extentionPointIncrementVector*i);
174 int numberOfPositions = positions.size();
175 for (
int j = numberOfPositions - 1; j >= 0; j--)
177 points->InsertNextPoint(positions[j](0),positions[j](1),positions[j](2));
179 for (
int j = 0; j < numberOfPositions-1; j++)
181 vtkIdType connection[2] = {j, j+1};
182 lines->InsertNextCell(2, connection);
184 retval->SetPoints(points);
185 retval->SetLines(lines);
196 Eigen::MatrixXd branchPositions = branchPtr->getPositions();
197 std::vector< Eigen::Vector3d > positions;
199 for (
int i = startIndex; i >=0; i--)
200 positions.push_back(branchPositions.col(i));
215 std::vector< Eigen::Vector3d > RouteToTarget::smoothBranch(
BranchPtr branchPtr,
int startIndex, Eigen::MatrixXd startPosition)
221 double branchRadius = branchPtr->findBranchRadius();
226 Eigen::MatrixXd positions = branchPtr->getPositions();
227 splineX->AddPoint(0,startPosition(0));
228 splineY->AddPoint(0,startPosition(1));
229 splineZ->AddPoint(0,startPosition(2));
235 if(!branchPtr->getParentBranch())
237 splineX->AddPoint(startIndex,positions(0,0));
238 splineY->AddPoint(startIndex,positions(1,0));
239 splineZ->AddPoint(startIndex,positions(2,0));
243 Eigen::MatrixXd parentPositions = branchPtr->getParentBranch()->getPositions();
244 splineX->AddPoint(startIndex,parentPositions(0,parentPositions.cols()-1));
245 splineY->AddPoint(startIndex,parentPositions(1,parentPositions.cols()-1));
246 splineZ->AddPoint(startIndex,parentPositions(2,parentPositions.cols()-1));
252 double maxAcceptedDistanceToOriginalPosition = std::max(branchRadius - 1, 1.0);
253 double maxDistanceToOriginalPosition = maxAcceptedDistanceToOriginalPosition + 1;
254 int maxDistanceIndex = -1;
255 std::vector< Eigen::Vector3d > smoothingResult;
258 while (maxDistanceToOriginalPosition >= maxAcceptedDistanceToOriginalPosition && splineX->GetNumberOfPoints() < startIndex)
260 if(maxDistanceIndex > 0)
263 splineX->AddPoint(maxDistanceIndex,positions(0,startIndex - maxDistanceIndex));
264 splineY->AddPoint(maxDistanceIndex,positions(1,startIndex - maxDistanceIndex));
265 splineZ->AddPoint(maxDistanceIndex,positions(2,startIndex - maxDistanceIndex));
269 maxDistanceToOriginalPosition = 0.0;
270 smoothingResult.clear();
271 for(
int j=0; j<=startIndex; j++)
273 double splineParameter = j;
274 Eigen::Vector3d tempPoint;
275 tempPoint(0) = splineX->Evaluate(splineParameter);
276 tempPoint(1) = splineY->Evaluate(splineParameter);
277 tempPoint(2) = splineZ->Evaluate(splineParameter);
278 smoothingResult.push_back(tempPoint);
283 if (distance > maxDistanceToOriginalPosition)
285 maxDistanceToOriginalPosition = distance;
286 maxDistanceIndex = j;
291 return smoothingResult;
296 QString RTTpath = services->patient()->getActivePatientFolder() +
"/RouteToTargetInformation/";
297 QDir RTTDirectory(RTTpath);
298 if (!RTTDirectory.exists())
299 RTTDirectory.mkpath(RTTpath);
302 QString filePath = RTTpath + QDateTime::currentDateTime().toString(format) +
"_RouteToTargetInformation.txt";
304 QFile outfile(filePath);
305 if (outfile.open(QIODevice::ReadWrite))
307 QTextStream stream(&outfile);
309 stream <<
"#Target position:" << endl;
310 stream << mTargetPosition(0) <<
" " << mTargetPosition(1) <<
" " << mTargetPosition(2) <<
" " << endl;
311 if (mProjectedBranchPtr)
313 stream <<
"#Route to target generations:" << endl;
314 stream << mProjectedBranchPtr->findGenerationNumber() << endl;
317 stream <<
"#Trachea length (mm):" << endl;
318 BranchPtr trachea = mBranchListPtr->getBranches()[0];
319 int numberOfPositionsInTrachea = trachea->getPositions().cols();
320 double tracheaLength =
calculateRouteLength(smoothBranch(trachea, numberOfPositionsInTrachea-1, trachea->getPositions().col(numberOfPositionsInTrachea-1)));
321 stream << tracheaLength << endl;
323 stream <<
"#Route to target length - from Carina (mm):" << endl;
325 stream <<
"#Extended route to target length - from Carina (mm):" << endl;
332 double routeLenght = 0;
333 for (
int i=0; i<route.size()-1; i++)
335 double d0 = route[i+1](0) - route[i](0);
336 double d1 = route[i+1](1) - route[i](1);
337 double d2 = route[i+1](2) - route[i](2);
339 routeLenght += sqrt( d0*d0 +d1*d1 + d2*d2 );
348 if (mExtendedRoutePositions.empty())
350 std::cout <<
"mExtendedRoutePositions is empty." << std::endl;
354 int numberOfExtendedPositions = mExtendedRoutePositions.size() - mRoutePositions.size();
356 ofstream out(filename.toStdString().c_str());
357 out <<
"# [xPos yPos zPos BranchingPoint (0=Normal, 1=Branching position, 2=Extended from airway to target)] ";
358 out <<
"Number of positions: ";
359 out << mExtendedRoutePositions.size();
362 for (
int i = 1; i < mExtendedRoutePositions.size(); i++)
364 out << mExtendedRoutePositions[i](0) <<
" ";
365 out << mExtendedRoutePositions[i](1) <<
" ";
366 out << mExtendedRoutePositions[i](2) <<
" ";
368 if ( std::find(mBranchingIndex.begin(), mBranchingIndex.end(), i - numberOfExtendedPositions) != mBranchingIndex.end() )
370 else if (i <= numberOfExtendedPositions)
384 if ( mRoutePositions.empty() || mExtendedRoutePositions.empty() )
386 std::cout <<
"mRoutePositions is empty." << std::endl;
390 int numberOfExtendedPositions = mExtendedRoutePositions.size() - mRoutePositions.size();
392 for (
int i = 1; i < mExtendedRoutePositions.size(); i++)
394 QJsonObject position;
395 position.insert(
"x", mExtendedRoutePositions[i](0) );
396 position.insert(
"y", mExtendedRoutePositions[i](1) );
397 position.insert(
"z", mExtendedRoutePositions[i](2) );
399 if ( std::find(mBranchingIndex.begin(), mBranchingIndex.end(), i - numberOfExtendedPositions) != mBranchingIndex.end() )
400 position.insert(
"Flag", 1);
401 else if (i <= numberOfExtendedPositions)
402 position.insert(
"Flag", 2);
404 position.insert(
"Flag", 0);
406 array.append(position);
416 for (
int i=1; i<line.cols(); i++)
425 double d0 = p1(0) - p2(0);
426 double d1 = p1(1) - p2(1);
427 double d2 = p1(2) - p2(2);
429 double D = sqrt( d0*d0 + d1*d1 + d2*d2 );
double findDistanceToLine(Eigen::MatrixXd point, Eigen::MatrixXd line)
boost::shared_ptr< class VisServices > VisServicesPtr
vtkSmartPointer< class vtkCellArray > vtkCellArrayPtr
vtkSmartPointer< vtkPoints > vtkPointsPtr
void processCenterline(MeshPtr mesh)
vtkPolyDataPtr addVTKPoints(std::vector< Eigen::Vector3d > positions)
std::vector< Eigen::Vector3d > getBranchPositions(BranchPtr branchPtr, int startIndex)
QString timestampSecondsFormat()
boost::shared_ptr< class Branch > BranchPtr
double findDistance(Eigen::MatrixXd p1, Eigen::MatrixXd p2)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
void findClosestPointInBranches(Vector3D targetCoordinate_r)
void searchBranchUp(BranchPtr searchBranchPtr, int startIndex)
vtkPolyDataPtr findRouteToTarget(PointMetricPtr targetPoint)
void addRouteInformationToFile(VisServicesPtr services)
vtkPolyDataPtr findExtendedRoute(PointMetricPtr targetPoint)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
QJsonArray makeMarianaCenterlineJSON()
double calculateRouteLength(std::vector< Eigen::Vector3d > route)
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
boost::shared_ptr< class Mesh > MeshPtr
void findRoutePositions()
void makeMarianaCenterlineFile(QString filename)
Eigen::MatrixXd getCenterlinePositions(vtkPolyDataPtr centerline_r)
Namespace for all CustusX production code.
boost::shared_ptr< class PointMetric > PointMetricPtr