15 #include <vtkPolyData.h> 16 #include <vtkCardinalSpline.h> 18 #include <boost/math/special_functions/fpclassify.hpp> 39 mBranches.push_back(b);
44 if(b->getParentBranch())
45 b->getParentBranch()->deleteChildBranches();
47 for(
int i = 0; i < mBranches.size(); i++ )
49 if (b == mBranches[i])
51 mBranches.erase(mBranches.begin() + i);
69 std::vector<int> branchNumbersToBeDeleted;
70 for(
int i = 0; i < mBranches.size(); i++ )
72 int generationCounter = 1;
74 while (currentBranch->getParentBranch()){
76 currentBranch = currentBranch->getParentBranch();
77 if (generationCounter > maxGeneration)
79 branchNumbersToBeDeleted.push_back(i);
86 for (
int i = branchNumbersToBeDeleted.size() - 1; i >= 0; i-- )
100 if(!branch->getParentBranch())
101 branch->setBronchoscopeRotation(0);
104 double parentRotation = branch->getParentBranch()->getBronchoscopeRotation();
105 Eigen::MatrixXd branchOrientations = branch->getOrientations();
106 Vector3D branchOrientationStart = branchOrientations.leftCols(std::min(25, (
int) branchOrientations.cols())).rowwise().mean();
107 Eigen::MatrixXd parentBranchOrientations = branch->getParentBranch()->getOrientations();
108 Vector3D parentBranchOrientationEnd = parentBranchOrientations.rightCols(std::min(50, (
int) parentBranchOrientations.cols())).rowwise().mean();
113 branch->setBronchoscopeBendingDirection(bendingDirection);
114 branch->setBronchoscopeRotation(bronchoscopeRotation);
117 branchVector childBranches = branch->getChildBranches();
118 for(
int i=0; i<childBranches.size(); i++)
124 double bronchoscopeRotation;
127 Vector3D up =
cross(parentBranchOrientation, xVector).normalized();
131 bronchoscopeRotation = acos( up.dot(bendingDirection) );
135 if(parentBranchOrientation.dot(N) < 0)
136 bronchoscopeRotation = -bronchoscopeRotation;
138 double rotationDifferenceFromParent = bronchoscopeRotation - parentRotation;
141 if ( rotationDifferenceFromParent >
M_PI )
142 rotationDifferenceFromParent = rotationDifferenceFromParent - 2*
M_PI;
143 else if ( rotationDifferenceFromParent < -M_PI )
144 rotationDifferenceFromParent = rotationDifferenceFromParent + 2*
M_PI;
148 bronchoscopeRotation = bronchoscopeRotation + M_PI;
150 bronchoscopeRotation = bronchoscopeRotation - M_PI;
153 rotationDifferenceFromParent = bronchoscopeRotation - parentRotation;
154 if( rotationDifferenceFromParent > M_PI )
155 bronchoscopeRotation = bronchoscopeRotation -
M_PI;
156 else if( rotationDifferenceFromParent < -M_PI )
157 bronchoscopeRotation = bronchoscopeRotation +
M_PI;
163 return bronchoscopeRotation;
175 C(1) = - ( ( N(2) - N(0)*A(2)/A(0) ) / ( N(1) - N(0)*A(1)/A(0) ) ) * C(2);
176 if(boost::math::isnan(C(1)) || boost::math::isinf(C(1)))
181 C(0) = - ( A(1)*C(1) + A(2)*C(2) ) / A(0);
193 for (
int i = 0; i < mBranches.size(); i++)
195 Eigen::MatrixXd orientations = mBranches[i]->getOrientations();
196 Eigen::MatrixXd newOrientations(orientations.rows(),orientations.cols());
197 int numberOfColumns = orientations.cols();
198 for (
int j = 0; j < numberOfColumns; j++)
200 newOrientations.col(j) = orientations.block(0,std::max(j-2,0),orientations.rows(),std::min(5,numberOfColumns-j)).rowwise().mean();
201 newOrientations.col(j) = newOrientations.col(j) / newOrientations.col(j).norm();
203 mBranches[i]->setOrientations(newOrientations);
209 for (
int i = 0; i < mBranches.size(); i++)
211 Eigen::VectorXd radius = mBranches[i]->getRadius();
212 Eigen::VectorXd newRadius(radius.rows(),radius.cols());
213 int numberOfPoints = radius.size();
214 for (
int j = 0; j < numberOfPoints; j++)
216 newRadius[j] = radius.segment(std::max(j-2,0), std::min(5,numberOfPoints-j)).mean();
218 mBranches[i]->setRadius(newRadius);
224 BranchPtr branchWithLargestRadius = mBranches[0];
225 double largestRadius = mBranches[0]->getAverageRadius();
227 for (
int i = 1; i < mBranches.size(); i++)
229 if (mBranches[i]->getAverageRadius() > largestRadius)
231 largestRadius = mBranches[i]->getAverageRadius();
232 branchWithLargestRadius = mBranches[i];
236 return branchWithLargestRadius;
242 for (
int i = 0; i < mBranches.size(); i++)
244 Eigen::MatrixXd positions = mBranches[i]->getPositions();
246 if (mBranches[i]->getParentBranch())
248 Eigen::MatrixXd parentPositions = mBranches[i]->getParentBranch()->getPositions();
249 Eigen::MatrixXd positionsResized(positions.rows(), positions.cols()+1);
250 positionsResized.col(0) = parentPositions.rightCols(1);
251 positionsResized.rightCols(positions.cols()) = positions;
252 positions = positionsResized;
255 std::vector<Eigen::Vector3d> interpolatedPositions;
256 for (
int j = 0; j < positions.cols()-1; j++)
258 int interpolationFactor =
static_cast<int>(
std::ceil( ( positions.col(j+1) - positions.col(j) ).norm() / resolution ));
259 for (
int k = 0; k < interpolationFactor; k++){
260 Eigen::Vector3d interpolationPoint;
261 interpolationPoint[0] = (positions(0,j)*(interpolationFactor-k) + positions(0,j+1)*(k) ) / interpolationFactor;
262 interpolationPoint[1] = (positions(1,j)*(interpolationFactor-k) + positions(1,j+1)*(k) ) / interpolationFactor;
263 interpolationPoint[2] = (positions(2,j)*(interpolationFactor-k) + positions(2,j+1)*(k) ) / interpolationFactor;
264 interpolatedPositions.push_back(interpolationPoint);
267 if (mBranches[i]->getParentBranch())
269 Eigen::MatrixXd positionsResized(positions.rows(), positions.cols()-1);
270 positionsResized = positions.rightCols(positionsResized.cols());
271 positions = positionsResized;
273 Eigen::MatrixXd interpolationResult(3 , interpolatedPositions.size());
274 for (
int j = 0; j < interpolatedPositions.size(); j++)
276 interpolationResult(0,j) = interpolatedPositions[j](0);
277 interpolationResult(1,j) = interpolatedPositions[j](1);
278 interpolationResult(2,j) = interpolatedPositions[j](2);
280 mBranches[i]->setPositions(interpolationResult);
287 for (
int i = 0; i < mBranches.size(); i++)
289 Eigen::MatrixXd positions = mBranches[i]->getPositions();
290 int numberOfInputPoints = positions.cols();
293 double branchLength = (positions.rightCols(1) - positions.leftCols(1)).norm();
294 int numberOfControlPoints =
std::ceil(branchLength/controlPointDistance);
295 numberOfControlPoints = std::max(numberOfControlPoints, 2);
302 for(
int j=0; j<numberOfControlPoints; j++)
304 int indexP = (j*numberOfInputPoints)/numberOfControlPoints;
306 splineX->AddPoint(indexP,positions(0,indexP));
307 splineY->AddPoint(indexP,positions(1,indexP));
308 splineZ->AddPoint(indexP,positions(2,indexP));
311 splineX->AddPoint(numberOfInputPoints-1,positions(0,numberOfInputPoints-1));
312 splineY->AddPoint(numberOfInputPoints-1,positions(1,numberOfInputPoints-1));
313 splineZ->AddPoint(numberOfInputPoints-1,positions(2,numberOfInputPoints-1));
316 Eigen::MatrixXd smoothingResult(3 , numberOfInputPoints);
317 for(
int j=0; j<numberOfInputPoints; j++)
319 double splineParameter = j;
320 smoothingResult(0,j) = splineX->Evaluate(splineParameter);
321 smoothingResult(1,j) = splineY->Evaluate(splineParameter);
322 smoothingResult(2,j) = splineZ->Evaluate(splineParameter);
324 mBranches[i]->setPositions(smoothingResult);
333 Eigen::MatrixXd positionsNotUsed_r = positions_r;
338 Eigen::MatrixXd::Index startIndex;
340 while (positionsNotUsed_r.cols() > 0)
342 if (!mBranches.empty())
344 double minDistance = 1000;
345 for (
int i = 0; i < mBranches.size(); i++)
347 std::pair<std::vector<Eigen::MatrixXd::Index>, Eigen::VectorXd> distances;
348 distances =
dsearchn(positionsNotUsed_r, mBranches[i]->getPositions());
349 double d = distances.second.minCoeff(&index);
353 branchToSplit = mBranches[i];
359 std::pair<Eigen::MatrixXd::Index, double> dsearchResult =
dsearch(positionsNotUsed_r.col(startIndex) , branchToSplit->getPositions());
360 splitIndex = dsearchResult.first;
363 startIndex = positionsNotUsed_r.cols() - 1;
365 std::pair<Eigen::MatrixXd,Eigen::MatrixXd > connectedPointsResult =
findConnectedPointsInCT(startIndex , positionsNotUsed_r);
366 Eigen::MatrixXd branchPositions = connectedPointsResult.first;
367 positionsNotUsed_r = connectedPointsResult.second;
369 if (branchPositions.cols() >= 5)
372 newBranch->setPositions(branchPositions);
373 mBranches.push_back(newBranch);
375 if (mBranches.size() > 1)
377 if ((splitIndex + 1 >= 5) && (branchToSplit->getPositions().cols() - splitIndex - 1 >= 5))
383 Eigen::MatrixXd branchToSplitPositions = branchToSplit->getPositions();
384 newBranchFromSplit->setPositions(branchToSplitPositions.rightCols(branchToSplitPositions.cols() - splitIndex - 1));
385 branchToSplit->setPositions(branchToSplitPositions.leftCols(splitIndex + 1));
386 mBranches.push_back(newBranchFromSplit);
387 newBranchFromSplit->setParentBranch(branchToSplit);
388 newBranch->setParentBranch(branchToSplit);
389 newBranchFromSplit->setChildBranches(branchToSplit->getChildBranches());
390 branchVector branchToSplitChildren = branchToSplit->getChildBranches();
391 for (
int i = 0; i < branchToSplitChildren.size(); i++)
392 branchToSplitChildren[i]->setParentBranch(newBranchFromSplit);
393 branchToSplit->deleteChildBranches();
394 branchToSplit->addChildBranch(newBranchFromSplit);
395 branchToSplit->addChildBranch(newBranch);
397 else if (splitIndex + 1 < 5)
402 newBranch->setParentBranch(branchToSplit->getParentBranch());
403 if(branchToSplit->getParentBranch())
404 branchToSplit->getParentBranch()->addChildBranch(newBranch);
406 else if (branchToSplit->getPositions().cols() - splitIndex - 1 < 5)
410 newBranch->setParentBranch(branchToSplit);
411 branchToSplit->addChildBranch(newBranch);
424 for (
int i = 0; i < mBranches.size(); i++)
427 b->setPositions(mBranches[i]->getPositions());
428 retval->addBranch(b);
431 std::vector<BranchPtr> branches = retval->getBranches();
432 Eigen::MatrixXd positions;
433 Eigen::MatrixXd orientations;
434 for (
int i = 0; i < branches.size(); i++)
436 positions = branches[i]->getPositions();
437 orientations = branches[i]->getOrientations();
438 std::pair<std::vector<Eigen::MatrixXd::Index>, Eigen::VectorXd> distanceData;
439 distanceData =
dsearchn(positions, trackingPositions);
440 Eigen::VectorXd distance = distanceData.second;
441 for (
int j = positions.cols() - 1; j >= 0; j--)
443 if (distance(j) > maxDistance)
446 orientations =
eraseCol(j, orientations);
449 branches[i]->setPositions(positions);
457 for (
int i = 0; i < branchVector.size(); i++)
459 Eigen::MatrixXd positions = branchVector[i]->getPositions();
460 Eigen::MatrixXd orientations = branchVector[i]->getOrientations();
462 for (
int i = positions.cols()-2; i > 0; i--){
463 double distance = (positions.col(i) - positions.col(i+1)).norm();
464 if ( distance < minPointDistance )
467 orientations =
eraseCol(i,orientations);
470 branchVector[i]->setPositions(positions);
484 branch->setLap(name);
486 for(
int i=0; i<bv.size(); i++)
493 return branch->getLap();
498 double d0 = p1(0) - p2(0);
499 double d1 = p1(1) - p2(1);
500 double d2 = p1(2) - p2(2);
502 double D = sqrt( d0*d0 + d1*d1 + d2*d2 );
509 double minDistance = 100000;
511 for (
int i = 0; i < mBranches.size(); i++)
513 Eigen::MatrixXd positions = mBranches[i]->getPositions();
514 for (
int j = 0; j < positions.cols(); j++)
516 double D =
findDistance(positions.col(j), targetCoordinate_r);
520 minDistanceBranch = mBranches[i];
525 return minDistanceBranch;
552 int positionCounter = 0;
553 for (
size_t i = 0; i < mBranches.size(); ++i)
555 Eigen::MatrixXd positions = mBranches[i]->getPositions();
559 points->InsertNextPoint(positions(0,0),positions(1,0),positions(2,0));
560 points->InsertNextPoint(positions(0,positions.cols()-1),positions(1,positions.cols()-1),positions(2,positions.cols()-1));
561 vtkIdType connection[2] = {positionCounter-1, positionCounter};
562 lines->InsertNextCell(2, connection);
567 for (
int j = 0; j < positions.cols(); ++j)
570 points->InsertNextPoint(positions(0,j),positions(1,j),positions(2,j));
571 if (j < positions.cols()-1)
573 vtkIdType connection[2] = {positionCounter-1, positionCounter};
574 lines->InsertNextCell(2, connection);
581 int this_branchs_first_point_in_full_polydata_point_list = 0;
582 for(
size_t i = 0; i < mBranches.size(); ++i)
586 if(!straightBranches)
587 this_branchs_first_point_in_full_polydata_point_list += mBranches[i-1]->getPositions().cols();
589 this_branchs_first_point_in_full_polydata_point_list += 2;
591 int parent_index_in_branch_list = mBranches[i]->findParentIndex(mBranches);
593 if(parent_index_in_branch_list > -1)
595 int parent_branch_last_point_in_full_polydata = 0;
596 for(
int j = 0; j <= parent_index_in_branch_list; ++j)
598 if(!straightBranches)
599 parent_branch_last_point_in_full_polydata += mBranches[j]->getPositions().cols() - 1;
601 parent_branch_last_point_in_full_polydata += (1 + j*2);
603 vtkIdType connection[2] = {parent_branch_last_point_in_full_polydata, this_branchs_first_point_in_full_polydata_point_list};
604 lines->InsertNextCell(2, connection);
610 retval->SetPoints(points);
611 retval->SetLines(lines);
616 Eigen::MatrixXd
sortMatrix(
int rowNumber, Eigen::MatrixXd matrix)
618 for (
int i = 0; i < matrix.cols() - 1; i++) {
619 for (
int j = i + 1; j < matrix.cols(); j++) {
620 if (matrix(rowNumber,i) > matrix(rowNumber,j)){
621 matrix.col(i).swap(matrix.col(j));
630 Eigen::MatrixXd
eraseCol(
int removeIndex, Eigen::MatrixXd positions)
632 positions.block(0 , removeIndex , positions.rows() , positions.cols() - removeIndex - 1) = positions.rightCols(positions.cols() - removeIndex - 1);
633 positions.conservativeResize(Eigen::NoChange, positions.cols() - 1);
637 std::pair<Eigen::MatrixXd::Index, double>
dsearch(Eigen::Vector3d p, Eigen::MatrixXd positions)
639 Eigen::MatrixXd::Index index;
641 (positions.colwise() - p).colwise().squaredNorm().minCoeff(&index);
642 double d = (positions.col(index) - p).norm();
644 return std::make_pair(index , d);
647 std::pair<std::vector<Eigen::MatrixXd::Index>, Eigen::VectorXd >
dsearchn(Eigen::MatrixXd p1, Eigen::MatrixXd p2)
649 Eigen::MatrixXd::Index index;
650 std::vector<Eigen::MatrixXd::Index> indexVector;
651 Eigen::VectorXd D(p1.cols());
652 for (
int i = 0; i < p1.cols(); i++)
655 (p2.colwise() - p1.col(i)).colwise().squaredNorm().minCoeff(&index);
656 D(i) = (p2.col(index) - p1.col(i)).norm();
657 indexVector.push_back(index);
659 return std::make_pair(indexVector , D);
665 Eigen::MatrixXd thisPosition(3,1);
666 std::vector<Eigen::MatrixXd> branchPositionsVector;
667 thisPosition = positionsNotUsed.col(startIndex);
668 branchPositionsVector.push_back(thisPosition);
669 positionsNotUsed =
eraseCol(startIndex,positionsNotUsed);;
671 while (positionsNotUsed.cols() > 0)
673 std::pair<Eigen::MatrixXd::Index, double > minDistance =
dsearch(thisPosition, positionsNotUsed);
674 Eigen::MatrixXd::Index index = minDistance.first;
675 double d = minDistance.second;
679 thisPosition = positionsNotUsed.col(index);
680 positionsNotUsed =
eraseCol(index,positionsNotUsed);
682 branchPositionsVector.push_back(thisPosition);
686 Eigen::MatrixXd branchPositions(3,branchPositionsVector.size());
688 for (
int j = 0; j < branchPositionsVector.size(); j++)
690 branchPositions.block(0,j,3,1) = branchPositionsVector[j];
693 return std::make_pair(branchPositions, positionsNotUsed);
712 double branchRadius = branchPtr->findBranchRadius()/2;
717 Eigen::MatrixXd positions = branchPtr->getPositions();
718 splineX->AddPoint(0,startPosition(0));
719 splineY->AddPoint(0,startPosition(1));
720 splineZ->AddPoint(0,startPosition(2));
725 if(!branchPtr->getParentBranch())
727 splineX->AddPoint(startIndex,positions(0,0));
728 splineY->AddPoint(startIndex,positions(1,0));
729 splineZ->AddPoint(startIndex,positions(2,0));
733 Eigen::MatrixXd parentPositions = branchPtr->getParentBranch()->getPositions();
734 splineX->AddPoint(startIndex,parentPositions(0,parentPositions.cols()-1));
735 splineY->AddPoint(startIndex,parentPositions(1,parentPositions.cols()-1));
736 splineZ->AddPoint(startIndex,parentPositions(2,parentPositions.cols()-1));
741 double maxAcceptedDistanceToOriginalPosition = std::max(branchRadius - 1, 1.0);
742 double maxDistanceToOriginalPosition = maxAcceptedDistanceToOriginalPosition + 1;
743 int maxDistanceIndex = -1;
744 std::vector< Eigen::Vector3d > smoothingResult;
747 while (maxDistanceToOriginalPosition >= maxAcceptedDistanceToOriginalPosition && splineX->GetNumberOfPoints() < startIndex)
749 if(maxDistanceIndex > 0)
752 splineX->AddPoint(maxDistanceIndex,positions(0,startIndex - maxDistanceIndex));
753 splineY->AddPoint(maxDistanceIndex,positions(1,startIndex - maxDistanceIndex));
754 splineZ->AddPoint(maxDistanceIndex,positions(2,startIndex - maxDistanceIndex));
758 maxDistanceToOriginalPosition = 0.0;
759 smoothingResult.clear();
760 for(
int j=0; j<=startIndex; j++)
762 double splineParameter = j;
763 Eigen::Vector3d tempPoint;
764 tempPoint(0) = splineX->Evaluate(splineParameter);
765 tempPoint(1) = splineY->Evaluate(splineParameter);
766 tempPoint(2) = splineZ->Evaluate(splineParameter);
767 smoothingResult.push_back(tempPoint);
770 double distance =
dsearch(tempPoint, positions).second;
772 if (distance > maxDistanceToOriginalPosition)
774 maxDistanceToOriginalPosition = distance;
775 maxDistanceIndex = j;
780 return smoothingResult;
std::vector< Eigen::Vector3d > smoothBranch(BranchPtr branchPtr, int startIndex, Eigen::MatrixXd startPosition)
std::pair< Eigen::MatrixXd, Eigen::MatrixXd > findConnectedPointsInCT(int startIndex, Eigen::MatrixXd positionsNotUsed)
Vector3D ceil(const Vector3D &a)
Eigen::MatrixXd eraseCol(int removeIndex, Eigen::MatrixXd positions)
QString findClosestLungLap(Vector3D position)
boost::shared_ptr< class BranchList > BranchListPtr
vtkSmartPointer< class vtkCellArray > vtkCellArrayPtr
double bendingDirectionToBronchoscopeRotation(Vector3D bendingDirection, Vector3D parentBranchOrientation, double parentRotation)
BranchListPtr removePositionsForLocalRegistration(Eigen::MatrixXd trackingPositions, double maxDistance)
Vector3D calculateBronchoscopeBendingDirection(Vector3D A, Vector3D B)
vtkSmartPointer< vtkPoints > vtkPointsPtr
boost::shared_ptr< class Branch > BranchPtr
void calculateBronchoscopeRotation(BranchPtr branch)
void addBranch(BranchPtr b)
BranchPtr findClosestBranch(Vector3D targetCoordinate_r)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
void findBranchesInCenterline(Eigen::MatrixXd positions_r, bool sortByZindex=true)
void findBronchoscopeRotation()
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
vtkPolyDataPtr createVtkPolyDataFromBranches(bool fullyConnected=false, bool straightBranches=false) const
BranchList::createVtkPolyDataFromBranches Return a VtkPolyData object created from the branches in th...
#define MAX_ROTATION_TO_TILT_DOWN_DEGREES
void markLungLap(QString name, Vector3D position)
void interpolateBranchPositions(double resolution)
void smoothBranchPositions(int controlPointDistance)
std::vector< BranchPtr > getBranches()
void excludeClosePositionsInCTCenterline(double minPointDistance)
BranchPtr findBranchWithLargestRadius()
void deleteBranch(BranchPtr b)
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
class org_custusx_registration_method_bronchoscopy_EXPORT Branch
void setLapName(BranchPtr branch, QString name)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
void selectGenerations(int maxGeneration)
Eigen::MatrixXd sortMatrix(int rowNumber, Eigen::MatrixXd matrix)
std::pair< std::vector< Eigen::MatrixXd::Index >, Eigen::VectorXd > dsearchn(Eigen::MatrixXd p1, Eigen::MatrixXd p2)
double findDistance(Vector3D p1, Vector3D p2)
void smoothOrientations()
std::pair< Eigen::MatrixXd::Index, double > dsearch(Eigen::Vector3d p, Eigen::MatrixXd positions)
std::vector< BranchPtr > branchVector
Namespace for all CustusX production code.