13 #include <boost/math/special_functions/round.hpp> 14 #include <vtkPolyData.h> 17 #include "vtkCardinalSpline.h" 20 #include <vtkImageData.h> 21 #include <vtkPointData.h> 23 #include "vtkCardinalSpline.h" 25 #include <vtkImageResample.h> 35 mAirwaysVolumeBoundaryExtention(10),
36 mAirwaysVolumeBoundaryExtentionTracheaStart(2),
37 mAirwaysVolumeSpacing(0.5)
47 mBloodVessel = bloodVessel;
53 int N = centerline_r->GetNumberOfPoints();
54 Eigen::MatrixXd CLpoints(3,N);
55 for(vtkIdType i = 0; i < N; i++)
58 centerline_r->GetPoint(i,p);
59 Eigen::Vector3d position;
60 position(0) = p[0]; position(1) = p[1]; position(2) = p[2];
61 CLpoints.block(0 , i , 3 , 1) = position;
68 mBranchListPtr = branches;
73 mOriginalSegmentedVolume = segmentedVolume;
79 mBranchListPtr->deleteAllBranches();
83 mBranchListPtr->findBranchesInCenterline(CLpoints_r);
85 mBranchListPtr->smoothBranchPositions(40);
86 mBranchListPtr->interpolateBranchPositions(0.1);
89 mBranchListPtr->smoothOrientations();
94 return mBranchListPtr;
106 mMergeWithOriginalAirways = mergeWithOriginalAirways;
109 if (mergeWithOriginalAirways)
111 if (mOriginalSegmentedVolume)
117 CX_LOG_WARNING() <<
"AirwaysFromCenterline::generateTubes: Segmented airways volume not set. Creating pure artificaial tubes around centerlines.";
143 std::vector<BranchPtr> branches = mBranchListPtr->getBranches();
146 int numberOfPoints = 0;
147 for (
int i = 0; i < branches.size(); i++)
148 numberOfPoints += branches[i]->getPositions().cols();
150 pointsPtr->SetNumberOfPoints(numberOfPoints);
153 for (
int i = 0; i < branches.size(); i++)
155 Eigen::MatrixXd positions = branches[i]->getPositions();
156 for (
int j = 0; j < positions.cols(); j++)
158 pointsPtr->SetPoint(pointIndex, positions(0,j), positions(1,j), positions(2,j));
163 pointsPtr->GetBounds(mBounds);
166 mBounds[0] -= mAirwaysVolumeBoundaryExtention;
167 mBounds[1] += mAirwaysVolumeBoundaryExtention;
168 mBounds[2] -= mAirwaysVolumeBoundaryExtention;
169 mBounds[3] += mAirwaysVolumeBoundaryExtention;
170 mBounds[4] -= mAirwaysVolumeBoundaryExtention;
171 mBounds[5] -= mAirwaysVolumeBoundaryExtentionTracheaStart;
173 mBounds[5] += mAirwaysVolumeBoundaryExtention;
175 mSpacing[0] = mAirwaysVolumeSpacing;
176 mSpacing[1] = mAirwaysVolumeSpacing;
177 mSpacing[2] = mAirwaysVolumeSpacing;
180 for (
int i = 0; i < 3; i++)
181 mDim[i] = static_cast<int>(
std::ceil((mBounds[i * 2 + 1] - mBounds[i * 2]) / mSpacing[i]));
183 mOrigin[0] = mBounds[0] + mSpacing[0] / 2;
184 mOrigin[1] = mBounds[2] + mSpacing[1] / 2;
185 mOrigin[2] = mBounds[4] + mSpacing[2] / 2;
188 airwaysVolumePtr->SetOrigin(mOrigin);
190 return airwaysVolumePtr;
196 if (!mOriginalSegmentedVolume)
197 return airwaysVolumePtr;
199 double magnificationFactor = mOriginalSegmentedVolume->GetSpacing()[0] / mAirwaysVolumeSpacing;
201 resampler->SetInterpolationModeToLinear();
202 resampler->SetAxisMagnificationFactor(0, magnificationFactor);
203 resampler->SetAxisMagnificationFactor(1, magnificationFactor);
204 resampler->SetAxisMagnificationFactor(2, magnificationFactor);
205 resampler->SetInputData(mOriginalSegmentedVolume);
207 airwaysVolumePtr = resampler->GetOutput();
209 Vector3D origin(airwaysVolumePtr->GetOrigin());
210 mOrigin[0] = origin[0];
211 mOrigin[1] = origin[1];
212 mOrigin[2] = origin[2];
214 Vector3D spacing(airwaysVolumePtr->GetSpacing());
217 airwaysVolumePtr->GetBounds(mBounds);
220 for (
int i = 0; i < 3; i++)
221 mDim[i] = static_cast<int>(
std::ceil((mBounds[i * 2 + 1] - mBounds[i * 2]) / mSpacing[i]));
223 return airwaysVolumePtr;
229 std::vector<BranchPtr> branches = mBranchListPtr->getBranches();
231 for (
int i = 0; i < branches.size(); i++)
233 Eigen::MatrixXd positions = branches[i]->getPositions();
235 int numberOfPositionsInBranch = positions.cols();
236 pointsPtr->SetNumberOfPoints(numberOfPositionsInBranch);
238 double radius = staticRadius;
241 radius = branches[i]->findBranchRadius();
242 if (mMergeWithOriginalAirways)
246 for (
int j = 0; j < numberOfPositionsInBranch; j++)
249 spherePos[0] = positions(0,j);
250 spherePos[1] = positions(1,j);
251 spherePos[2] = positions(2,j);
255 return airwaysVolumePtr;
262 int sphereBoundingBoxIndex[6];
264 for (
int i=0; i<3; i++)
266 centerIndex[i] =
static_cast<int>(
boost::math::round( (position[i]-mOrigin[i]) / mSpacing[i] ));
267 sphereBoundingBoxIndex[2*i] = std::max(
268 static_cast<int>(
boost::math::round( (position[i]-mOrigin[i] - radius) / mSpacing[i] )),
270 sphereBoundingBoxIndex[2*i+1] = std::min(
271 static_cast<int>(
boost::math::round( (position[i]-mOrigin[i] + radius) / mSpacing[i] )),
275 for (
int x = sphereBoundingBoxIndex[0]; x<=sphereBoundingBoxIndex[1]; x++)
276 for (
int y = sphereBoundingBoxIndex[2]; y<=sphereBoundingBoxIndex[3]; y++)
277 for (
int z = sphereBoundingBoxIndex[4]; z<=sphereBoundingBoxIndex[5]; z++)
279 double distanceFromCenter = sqrt((x-centerIndex[0])*mSpacing[0]*(x-centerIndex[0])*mSpacing[0] +
280 (y-centerIndex[1])*mSpacing[1]*(y-centerIndex[1])*mSpacing[1] +
281 (z-centerIndex[2])*mSpacing[2]*(z-centerIndex[2])*mSpacing[2]);
283 if (distanceFromCenter < radius)
285 unsigned char* dataPtrImage =
static_cast<unsigned char*
>(airwaysVolumePtr->GetScalarPointer(x,y,z));
286 dataPtrImage[0] = value;
290 return airwaysVolumePtr;
296 std::vector<BranchPtr> branches = mBranchListPtr->getBranches();
297 for (
int i=0; i<branches.size(); i++)
299 Eigen::MatrixXd positions = branches[i]->getPositions();
300 std::vector< Eigen::Vector3d > smoothedPositions =
smoothBranch(branches[i], positions.cols()-1, positions.col(positions.cols()-1));
301 for (
int j=0; j<smoothedPositions.size(); j++)
303 positions(0,j) = smoothedPositions[smoothedPositions.size() - j - 1](0);
304 positions(1,j) = smoothedPositions[smoothedPositions.size() - j - 1](1);
305 positions(2,j) = smoothedPositions[smoothedPositions.size() - j - 1](2);
307 branches[i]->setPositions(positions);
320 double minPointDistance = 0.5;
321 mBranchListPtr->excludeClosePositionsInCTCenterline(minPointDistance);
323 std::vector<BranchPtr> branches = mBranchListPtr->getBranches();
326 for (
int i = 0; i < branches.size(); i++)
328 Eigen::MatrixXd positions = branches[i]->getPositions();
329 int numberOfPositions = positions.cols();
331 if (branches[i]->getParentBranch())
333 Eigen::MatrixXd parentPositions = branches[i]->getParentBranch()->getPositions();
334 points->InsertNextPoint(parentPositions(0,parentPositions.cols()-1),parentPositions(1,parentPositions.cols()-1),parentPositions(2,parentPositions.cols()-1));
338 for (
int j = 0; j < numberOfPositions; j++)
340 points->InsertNextPoint(positions(0,j),positions(1,j),positions(2,j));
342 if (j>1 || branches[i]->getParentBranch())
344 vtkIdType connection[2] = {pointIndex-1, pointIndex};
345 lines->InsertNextCell(2, connection);
351 retval->SetPoints(points);
352 retval->SetLines(lines);
360 for (
int i=1; i<line.cols(); i++)
367 return std::make_pair(index , minDistance);
370 double findDistance(Eigen::MatrixXd p1, Eigen::MatrixXd p2)
372 double d0 = p1(0) - p2(0);
373 double d1 = p1(1) - p2(1);
374 double d2 = p1(2) - p2(2);
376 double D = sqrt( d0*d0 + d1*d1 + d2*d2 );
std::vector< Eigen::Vector3d > smoothBranch(BranchPtr branchPtr, int startIndex, Eigen::MatrixXd startPosition)
double findDistance(Eigen::MatrixXd p1, Eigen::MatrixXd p2)
BranchListPtr getBranchList()
vtkImageDataPtr initializeAirwaysVolumeFromOriginalSegmentation()
Vector3D ceil(const Vector3D &a)
boost::shared_ptr< class BranchList > BranchListPtr
vtkSmartPointer< class vtkCellArray > vtkCellArrayPtr
vtkPolyDataPtr getVTKPoints()
vtkImageDataPtr addSphereToImage(vtkImageDataPtr airwaysVolumePtr, double position[3], double radius)
void setSegmentedVolume(vtkImageDataPtr segmentedVolume)
vtkSmartPointer< vtkPoints > vtkPointsPtr
Eigen::MatrixXd getCenterlinePositions(vtkPolyDataPtr centerline_r)
void processCenterline(vtkPolyDataPtr centerline_r)
void setTypeToBloodVessel(bool bloodVessel)
vtkImageDataPtr initializeEmptyAirwaysVolume()
virtual ~AirwaysFromCenterline()
vtkPolyDataPtr generateTubes(double staticRadius=0, bool mergeWithOriginalAirways=false)
std::pair< int, double > findDistanceToLine(Eigen::Vector3d point, Eigen::MatrixXd line)
vtkImageDataPtr generateVtkImageData(Eigen::Array3i dim, Vector3D spacing, const unsigned char initValue, int components)
vtkSmartPointer< class vtkImageResample > vtkImageResamplePtr
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
void setBranches(BranchListPtr branches)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
vtkSmartPointer< class vtkCardinalSpline > vtkCardinalSplinePtr
vtkImageDataPtr addSpheresAlongCenterlines(vtkImageDataPtr airwaysVolumePtr, double staticRadius=0)
void smoothAllBranchesForVB()
Vector3D round(const Vector3D &a)
Namespace for all CustusX production code.