typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1,
typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2);
+ //--------------------------------------------------------------------
+ template<int Dimension>
+ void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo,
+ typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1,
+ typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2,
+ int dimension);
+
//--------------------------------------------------------------------
template<int Dimension>
void ComputeBBUnion(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo,
///--------------------------------------------------------------------
template<int Dimension>
+ void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo,
+ typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1,
+ typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2,
+ int dimension) {
+ typedef itk::BoundingBox<unsigned long, Dimension> BBType;
+ typedef typename BBType::PointType PointType;
+ PointType lastPoint;
+ PointType firstPoint;
+ firstPoint[dimension] = std::max(bbi1->GetMinimum()[dimension], bbi2->GetMinimum()[dimension]);
+ lastPoint[dimension] = std::min(bbi1->GetMaximum()[dimension], bbi2->GetMaximum()[dimension]);
+ bbo->SetMaximum(lastPoint);
+ bbo->SetMinimum(firstPoint);
+ }
+ //--------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------
+ template<int Dimension>
void ComputeBBUnion(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo,
typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1,
typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
{
ImagePointer temp = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
m_Object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
- m_Target = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
+ ImagePointer temp2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
// Remove object from support (keep initial image)
m_Support = clitk::Clone<ImageType>(temp);
clitk::AndNot<ImageType>(m_Support, m_Object, GetBackgroundValue());
+ // Remove object from target. Important because sometimes, there is
+ // overlap between target and object.
+ m_Target = clitk::Clone<ImageType>(temp2);
+ clitk::AndNot<ImageType>(m_Target, m_Object, GetBackgroundValue());
+
// Define filter to compute statics on mask image
typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatFilterType;
typename StatFilterType::Pointer statFilter = StatFilterType::New();
double mReverseThreshold=1.0;
ComputeOptimalThresholds(map, m_Target, bins, tolerance, mThreshold, mReverseThreshold);
+ // DD(mThreshold);
+ // DD(mReverseThreshold);
+
// Use the threshold to compute new support
int s1 = GetSupportSize();
if (mThreshold > 0.0) {
s2 = statFilter->GetCount(GetForegroundValue());
}
+ // Check threshold, if we gain nothing, we force to max/min thresholds
+ // DD(GetSupportSize());
+ // DD(s1);
+ // DD(s2);
+ if (s1 >= GetSupportSize()) mThreshold = 0.0;
+ if (s2 >= GetSupportSize()) mReverseThreshold = 1.0;
+
// Set results values
m_Info.threshold = mThreshold;
m_Info.sizeAfterThreshold = s1;
// sliceRelPosFilter->PrintOptions();
sliceRelPosFilter->Update();
typename FloatImageType::Pointer map = sliceRelPosFilter->GetFuzzyMap();
+ writeImage<FloatImageType>(map, "fuzzy_0_"+toString(clitk::rad2deg(angle))+".mha");
- // Resize map like object to allow SetBackground
- map = clitk::ResizeImageLike<FloatImageType>(map, object, GetBackgroundValue());
+ // Resize object like map to allow SetBackground
+ ImagePointer temp = clitk::ResizeImageLike<ImageType>(object, map, GetBackgroundValue());
+ // writeImage<FloatImageType>(map, "fuzzy_1_"+toString(clitk::rad2deg(angle))+".mha");
// Remove initial object from the fuzzy map
- map = clitk::SetBackground<FloatImageType, ImageType>(map, object, GetForegroundValue(), 0.0, true);
+ map = clitk::SetBackground<FloatImageType, ImageType>(map, temp, GetForegroundValue(), 0.0, true);
+ writeImage<FloatImageType>(map, "fuzzy_2_"+toString(clitk::rad2deg(angle))+".mha");
// Resize the fuzzy map like the target, put 2.0 when outside
map = clitk::ResizeImageLike<FloatImageType>(map, target, 2.0); // Put 2.0 when out of initial map
+ writeImage<FloatImageType>(map, "fuzzy_3_"+toString(clitk::rad2deg(angle))+".mha");
// end
return map;
f->SetInput(map);
f->SetLabelInput(target);
f->UseHistogramsOn();
- f->SetHistogramParameters(bins, 0.0, 1.1);
+ f->SetHistogramParameters(bins, 0.0-(1.0/bins), 1.0+(1.0/bins));
f->Update();
int count = f->GetCount(GetForegroundValue());
+ // DD(count);
typename FloatStatFilterType::HistogramPointer h = f->GetHistogram(GetForegroundValue());
// Debug : dump histogram
<< "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
}
histogramFile.close();
+ std::ofstream histogramFile2(std::string("fuzzy_histo_R_"+toString(i)+".txt").c_str());
+ for(int j=bins-1; j>=0; j--) {
+ histogramFile2 << h->GetMeasurement(j,0)
+ << "\t" << h->GetFrequency(j)
+ << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
+ }
+ histogramFile2.close();
i++;
// Analyze the histogram (direct)
double sum = 0.0;
bool found = false;
threshold = 0.0;
- for(int j=0; j<bins; j++) {
+ for(int j=0; j<bins-1; j++) {
sum += ((double)h->GetFrequency(j)/(double)count);
+ // DD(j);
+ // DD(sum);
+ // DD(threshold);
+ // DD(h->GetBinMin(0,j));
+ // DD(h->GetBinMax(0,j));
if ((!found) && (sum > tolerance)) {
- if (j==0) threshold = h->GetBinMin(0,j);
- else threshold = h->GetBinMin(0,j-1); // the last before reaching the threshold
+ // We consider as threshold the laste before current, because
+ if (j==0)
+ threshold = h->GetBinMin(0,j);
+ else threshold = h->GetBinMin(0,j-1); // FIXME ? the last before reaching the threshold
+ // DD(threshold);
found = true;
+ j = bins;
}
}
sum = 0.0;
found = false;
reverseThreshold = 1.0;
- for(int j=bins-1; j>=0; j--) {
+ for(int j=bins-1; j>0; j--) {
sum += ((double)h->GetFrequency(j)/(double)count);
+ // DD(j);
+ // DD(sum);
+ // DD(reverseThreshold);
+ // DD(h->GetBinMin(0,j));
+ // DD(h->GetBinMax(0,j));
if ((!found) && (sum > tolerance)) {
- if (j==bins-1) reverseThreshold = h->GetBinMax(0,j);
- else reverseThreshold = h->GetBinMax(0,j+1);
+ if (j==bins-1)
+ reverseThreshold = h->GetBinMax(0,j);
+ else reverseThreshold = h->GetBinMax(0,j-1);// FIXME ? the last before reaching the threshold
+ // DD(reverseThreshold);
found = true;
+ j = -1;
}
}
+
}
//--------------------------------------------------------------------
{
assert((mainDirection==0) || (mainDirection==1));
typedef itk::ImageSliceIteratorWithIndex<ImageType> SliceIteratorType;
- SliceIteratorType siter = SliceIteratorType(input,
- input->GetLargestPossibleRegion());
+ SliceIteratorType siter = SliceIteratorType(input, input->GetLargestPossibleRegion());
siter.SetFirstDirection(0);
siter.SetSecondDirection(1);
siter.GoToBegin();
A = lA[i];
B = lB[i];
C = A;
-
// Check that the line is not a point (A=B)
bool p = (A[0] == B[0]) && (A[1] == B[1]);
PrintOptions();
}
+ if (this->GetFuzzyMapOnlyFlag()) this->ComputeFuzzyMapFlagOn();
+
// Get input pointer
input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
+ m_working_object = object;
+ m_working_input = input;
//--------------------------------------------------------------------
// Resample object to the same spacing than input
m_working_object = clitk::ResampleImageSpacing<ImageType>(object, input->GetSpacing());
this->template StopCurrentStep<ImageType>(m_working_object);
}
- else {
- m_working_object = object;
- }
//--------------------------------------------------------------------
- // Pad object to the same size than input
+ // Resize image according to common area (except in Z)
if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(m_working_object, input)) {
+ this->StartNewStep("Resize images (union in XY and like input in Z)");
+
+ /* OLD STUFF
this->StartNewStep("Pad object to the same size than input");
m_working_object = clitk::ResizeImageLike<ImageType>(m_working_object,
- input,
- this->GetObjectBackgroundValue());
+ input,
+ this->GetObjectBackgroundValue());
this->template StopCurrentStep<ImageType>(m_working_object);
+ */
+
+ // Compute union of bounding boxes in X and Y
+ static const unsigned int dim = ImageType::ImageDimension;
+ typedef itk::BoundingBox<unsigned long, dim> BBType;
+ typename BBType::Pointer bb1 = BBType::New();
+ ComputeBBFromImageRegion<ImageType>(m_working_object, m_working_object->GetLargestPossibleRegion(), bb1);
+ typename BBType::Pointer bb2 = BBType::New();
+ ComputeBBFromImageRegion<ImageType>(input, input->GetLargestPossibleRegion(), bb2);
+ typename BBType::Pointer bbo = BBType::New();
+ ComputeBBUnion<dim>(bbo, bb1, bb2);
+
+ //We set Z BB like input
+ typename ImageType::PointType maxs = bbo->GetMaximum();
+ typename ImageType::PointType mins = bbo->GetMinimum();
+ maxs[2] = bb2->GetMaximum()[2];
+ mins[2] = bb2->GetMinimum()[2];
+ bbo->SetMaximum(maxs);
+ bbo->SetMinimum(mins);
+
+ // Crop
+ m_working_input = clitk::ResizeImageLike<ImageType>(input, bbo, this->GetBackgroundValue());
+ m_working_object = clitk::ResizeImageLike<ImageType>(m_working_object,
+ m_working_input,
+ this->GetObjectBackgroundValue());
+ this->template StopCurrentStep<ImageType>(m_working_input);
}
- else {
- }
-
- /*
+
+ //--------------------------------------------------------------------
+ /* Steps :
- extract vector of slices in input, in object
- slice by slice rel position
- joint result
- post process
*/
-
//--------------------------------------------------------------------
// Extract input slices
this->StartNewStep("Extract input slices");
typedef clitk::ExtractSliceFilter<ImageType> ExtractSliceFilterType;
typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(input);
+ extractSliceFilter->SetInput(m_working_input);
extractSliceFilter->SetDirection(GetDirection());
extractSliceFilter->Update();
typedef typename ExtractSliceFilterType::SliceType SliceType;
// Extract object slices
this->StartNewStep("Extract object slices");
extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(m_working_object);//object);
+ extractSliceFilter->SetInput(m_working_object);
extractSliceFilter->SetDirection(GetDirection());
extractSliceFilter->Update();
std::vector<typename SliceType::Pointer> mObjectSlices;
int nb=0;
mObjectSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mObjectSlices[i], 0, true, 1, nb);
- // If no object and empty slices :
- if ((nb==0) && (this->GetFuzzyMapOnlyFlag())) {
+ // If no object and empty slices and if we need the full fuzzy map, create a dummy one.
+ if ((nb==0) && (this->GetComputeFuzzyMapFlag())) {
typename FloatSliceType::Pointer one = FloatSliceType::New();
one->CopyInformation(mObjectSlices[0]);
one->SetRegions(mObjectSlices[0]->GetLargestPossibleRegion());
one->Allocate();
one->FillBuffer(2.0);
mFuzzyMapSlices[i] = one;
- }
+ } // End nb==0 && GetComputeFuzzyMapFlag
else {
if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
-
+
// Select or not a single CCL ?
if (GetUseTheLargestObjectCCLFlag()) {
mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
relPosFilter->VerboseStepFlagOff();
relPosFilter->WriteStepFlagOff();
+ // relPosFilter->VerboseMemoryFlagOn();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()+"-"+toString(i));
+
relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
relPosFilter->SetInput(mInputSlices[i]);
relPosFilter->SetInputObject(mObjectSlices[i]);
relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
+
// This flag (InverseOrientation) *must* be set before
// AddOrientation because AddOrientation can change it.
relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
for(int j=0; j<this->GetNumberOfAngles(); j++) {
- // relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
relPosFilter->AddAnglesInRad(this->GetAngle1InRad(j), this->GetAngle2InRad(j));
- // DD(this->GetOrientationTypeString(j));
}
- // DD(this->GetInverseOrientationFlag());
- //relPosFilter->SetOrientationType(this->GetOrientationType());
relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
// should we stop after fuzzy map ?
relPosFilter->SetFuzzyMapOnlyFlag(this->GetFuzzyMapOnlyFlag());
+ relPosFilter->SetComputeFuzzyMapFlag(this->GetComputeFuzzyMapFlag());
// Go !
relPosFilter->Update();
// If we stop after the fuzzy map, store the fuzzy slices
- if (this->GetFuzzyMapOnlyFlag()) {
+ if (this->GetComputeFuzzyMapFlag()) {
mFuzzyMapSlices[i] = relPosFilter->GetFuzzyMap();
// writeImage<FloatSliceType>(mFuzzyMapSlices[i], "slice_"+toString(i)+".mha");
}
- else {
+
+ // Set input slices
+ if (!this->GetFuzzyMapOnlyFlag()) {
mInputSlices[i] = relPosFilter->GetOutput();
// Select main CC if needed
if (GetUniqueConnectedComponentBySliceFlag()) {
mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
- }
-
+ }
}
}
+
/*
// Select unique CC according to the most in a given direction
if (GetUniqueConnectedComponentBySliceAccordingToADirection()) {
ComputeCentroids
}
*/
- }
- }
- // Join the fuzzy map if needed
- if (this->GetFuzzyMapOnlyFlag()) {
- this->m_FuzzyMap = clitk::JoinSlices<FloatImageType>(mFuzzyMapSlices, input, GetDirection());
- this->template StopCurrentStep<FloatImageType>(this->m_FuzzyMap);
- return;
- }
+ } // End nb!=0 || GetComputeFuzzyMapFlagOFF
+
+ } // end for i mInputSlices
// Join the slices
- m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, input, GetDirection());
+ m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, m_working_input, GetDirection());
this->template StopCurrentStep<ImageType>(m_working_input);
+ // Join the fuzzy map if needed
+ if (this->GetComputeFuzzyMapFlag()) {
+ this->m_FuzzyMap = clitk::JoinSlices<FloatImageType>(mFuzzyMapSlices, m_working_input, GetDirection());
+ this->template StopCurrentStep<FloatImageType>(this->m_FuzzyMap);
+ if (this->GetFuzzyMapOnlyFlag()) return;
+ }
+
//--------------------------------------------------------------------
// Step 7: autocrop
if (this->GetAutoCropFlag()) {
Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0);
Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]);
- // Initialise all others supports
- // m_ListOfSupports["S1R"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S1L"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S2R"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S2L"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S3A"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S3P"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S4R"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S4L"] = m_ListOfSupports["Sup_to_Carina"];
- // m_ListOfSupports["S5"] = m_Mediastinum; // Not above Carina
- // m_ListOfSupports["S6"] = m_Mediastinum; // Not above Carina
-
// Read all support limits in a file and apply them
ReadSupportLimits(GetSupportLimitsFilename());
for(unsigned int i=0; i<m_ListOfSupportLimits.size(); i++) {
Support_LeftRight_S4R_S4L();
// Post limits of S1,S2,S4
- Support_Post_S1S2S4();
+ Support_Post_S2S4();
- // S3P
+ // S3P : "the anterior border is an imaginary horizontal line
+ // extending along the posterior wall of the trachea"
StartNewStep("[Support] Ant limits of S3P with trachea");
m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10);
- // S3A
+ // S3A : "Posteriorly, the station is limited by station 2R and 2L,
+ // but excludes the great vessels. An imaginary line joins the
+ // midpoint of the vessel in the anterior to posterior plane. It is
+ // here that station 2 contacts station 3a" ===> here limit with
+ // trachea only
StartNewStep("[Support] Ant limits of S3A with trachea");
m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10);
+
+ // S1RL - posterior limits when SI overlap with S3P
+ Support_Post_S1_S3P();
+
+ // S1RL - posterior limits with S2RL above sternal notch
+ Support_Post_S1_Ant_S2RL();
// I will do it later
// Below Carina S7,8,9,10
clitk::ExtractLymphStationsFilter<ImageType>::
Support_LeftRight_S1R_S1L()
{
+ /*
+ Medially, station 1R and 1L are separated by the midline of the
+ trachea, whilst excluding the thyroid gland.
+ */
+
// Step S1RL : Left-Right
StartNewStep("[Support] Left-Right S1R S1L");
std::vector<ImagePointType> A;
// Right part
clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
- GetBackgroundValue(), 0, 10);
+ GetBackgroundValue(), 0, -10);
S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
m_ListOfSupports["S1R"] = S1R;
// Left part
clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
- GetBackgroundValue(), 0, -10);
+ GetBackgroundValue(), 0, 10);
S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
m_ListOfSupports["S1L"] = S1L;
StopCurrentStep<MaskImageType>(m_ListOfSupports["S1L"]);
Support_LeftRight_S2R_S2L()
{
// ---------------------------------------------------------------------------
- /* Step : S2RL LeftRight
- As for lymph node station 4R, 2R includes nodes extending to the
- left lateral border of the trachea
- Rod says: "For station 2 there is a shift, dividing 2R from 2L, from midline
- to the left paratracheal border."
+ /* Step : S2RL LeftRight As for lymph node station 4R, 2R includes
+ nodes extending to the left lateral border of the trachea.
+
+ Rod says: "For station 2 there is a shift in the IASLC definition
+ dividing 2R from 2L, from the midline to the left lateral
+ tracheal border. This is represented in the atlas as a vertical
+ line passing tangentially along the left lateral tracheal border
+ "
*/
StartNewStep("[Support] Separate 2R/2L according to Trachea");
MaskImagePointer S2R = m_ListOfSupports["S2R"];
Support_LeftRight_S4R_S4L()
{
// ---------------------------------------------------------------------------
- /* Step : S4RL LeftRight
-
- - 4R: includes right paratracheal nodes, and pretracheal nodes
- extending to the left lateral border of trachea
-
- - 4L: includes nodes to the left of the left lateral border of
- the trachea, medial to the ligamentum arteriosum
-
- => same than 2RL
+ /*
+ The medial border of station 4R is defined as an imaginary line
+ running vertically from the left lateral tracheal border. This is
+ the same medial border as was described for station 2R.
*/
StartNewStep("[Support] Left Right separation of 4R/4L");
template <class ImageType>
void
clitk::ExtractLymphStationsFilter<ImageType>::
-Support_Post_S1S2S4()
+Support_Post_S2S4()
{
- StartNewStep("[Support] Post limits of S1RL, S2RL, S4RL");
+ StartNewStep("[Support] Post limits of S2RL, S4RL");
double m_ApexOfTheChest = FindApexOfTheChest();
// Post limits with Trachea
- MaskImagePointer S1R = m_ListOfSupports["S1R"];
- MaskImagePointer S1L = m_ListOfSupports["S1L"];
+ // MaskImagePointer S1R = m_ListOfSupports["S1R"];
+ // MaskImagePointer S1L = m_ListOfSupports["S1L"];
MaskImagePointer S2R = m_ListOfSupports["S2R"];
MaskImagePointer S2L = m_ListOfSupports["S2L"];
MaskImagePointer S4R = m_ListOfSupports["S4R"];
MaskImagePointer S4L = m_ListOfSupports["S4L"];
- m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
- m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
+ // m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
+ // m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest);
m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest);
m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest);
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+Support_Post_S1_S3P()
+{
+ StartNewStep("[Support] If S1RL and S3P have Sup-Inf overlap, define S1RL posterior limits with S3P anterior limits (post wall trachea)");
+
+ // Get current supports
+ MaskImagePointer S1R = m_ListOfSupports["S1R"];
+ MaskImagePointer S1L = m_ListOfSupports["S1L"];
+
+ // Find extrema ant positions for 3P
+ std::vector<MaskImagePointType> A;
+ std::vector<MaskImagePointType> B;
+
+ // Crop S3P like S1R
+ MaskImagePointer S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
+ S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1R, GetBackgroundValue());
+
+ // Slice by slice, build the separation line
+ clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P,
+ GetBackgroundValue(), 2,
+ 1, true, // Ant-Post
+ 0, // Horizontal line
+ 0, // margins
+ A, B);
+
+ // clitk::WriteListOfLandmarks<MaskImageType>(A, "A-S1S3P.txt");
+ // clitk::WriteListOfLandmarks<MaskImageType>(B, "B-S1S3P.txt");
+
+ // Cut post to this line
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
+ GetBackgroundValue(),
+ 1, -10);
+
+ // Crop S3P like S1L (Redo for S1L)
+ S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
+ S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1L, GetBackgroundValue());
+
+ // Slice by slice, build the separation line
+ A.clear();
+ B.clear();
+ clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P,
+ GetBackgroundValue(), 2,
+ 1, true, // Ant-Post
+ 0, // Horizontal line
+ 0, // margins
+ A, B);
+ // Cut post to this line
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
+ GetBackgroundValue(),
+ 1, -10);
+
+ // Crop both images
+ S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
+ S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
+
+ StopCurrentStep<MaskImageType>(S1R);
+
+ m_ListOfSupports["S1R"] = S1R;
+ m_ListOfSupports["S1L"] = S1L;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+Support_Post_S1_Ant_S2RL()
+{
+ StartNewStep("[Support] Define S1RL posterior limits with S2RL anterior limits when overlap");
+
+ // Get RightLung
+ MaskImagePointer RightLung = this->GetAFDB()->template GetImage<MaskImageType>("RightLung");
+
+ // Find common area between S1 and S2
+ MaskImagePointType p_min;
+ MaskImagePointType p_max;
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2R"],
+ GetBackgroundValue(), 2, false, p_max);
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1R"],
+ GetBackgroundValue(), 2, true, p_min);
+ p_min[2] -= RightLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
+ p_max[2] += RightLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal)
+
+ if (p_min[2] > p_max[2]) {
+
+ // Crop RightLung
+ RightLung = clitk::Clone<MaskImageType>(RightLung);
+ RightLung = clitk::ResizeImageLike<MaskImageType>(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue());
+ RightLung = clitk::CropImageRemoveLowerThan<MaskImageType>(RightLung, 2, p_min[2], true, GetBackgroundValue());
+ RightLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(RightLung, 2, p_max[2], true, GetBackgroundValue());
+
+ // Find extrema ant positions for RightLung
+ std::vector<MaskImagePointType> A;
+ std::vector<MaskImagePointType> B;
+ clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(RightLung,
+ GetBackgroundValue(), 2,
+ 1, true, // Ant-Post
+ 0, // Horizontal line
+ 0, // margins
+ A, B);
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1R"],
+ A, B,
+ GetBackgroundValue(),
+ 1, -10);
+ // I add one pixel to abupt S2R to S1R
+ for(int i=0; i<A.size(); i++) {
+ A[i][1] -= RightLung->GetSpacing()[1];
+ B[i][1] -= RightLung->GetSpacing()[1];
+ }
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2R"],
+ A, B,
+ GetBackgroundValue(),
+ 1, 10);
+ }
+
+ // Get LeftLung, crop
+ MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2L"],
+ GetBackgroundValue(), 2, false, p_max);
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1L"],
+ GetBackgroundValue(), 2, true, p_min);
+ p_min[2] -= LeftLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
+ p_max[2] += LeftLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal)
+
+ if (p_min[2] > p_max[2]) {
+ LeftLung = clitk::ResizeImageLike<MaskImageType>(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue());
+ LeftLung = clitk::CropImageRemoveLowerThan<MaskImageType>(LeftLung, 2, p_min[2], true, GetBackgroundValue());
+ LeftLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(LeftLung, 2, p_max[2], true, GetBackgroundValue());
+
+ // Find extrema ant positions for LeftLung
+ std::vector<MaskImagePointType> A;
+ std::vector<MaskImagePointType> B;
+ clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(LeftLung,
+ GetBackgroundValue(), 2,
+ 1, true, // Ant-Post
+ 0, // Horizontal line
+ 0, // margins
+ A, B);
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1L"],
+ A, B,
+ GetBackgroundValue(),
+ 1, -10);
+ // I add one pixel to abupt S2R to S1R
+ for(int i=0; i<A.size(); i++) {
+ A[i][1] -= LeftLung->GetSpacing()[1];
+ B[i][1] -= LeftLung->GetSpacing()[1];
+ }
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2L"],
+ A, B,
+ GetBackgroundValue(),
+ 1, 10);
+ }
+}
+//--------------------------------------------------------------------
m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
m_Mediastinum = this->GetAFDB()->template GetImage <MaskImageType>("Mediastinum");
+ // DD(this->GetVerboseMemoryFlag());
+ // clitk::PrintMemory(this->GetVerboseMemoryFlag(), "Start");
+
// Clean some computer landmarks to force the recomputation
// FIXME -> to put elsewhere ?
this->GetAFDB()->RemoveTag("AntPostVesselsSeparation");
// Loop on RelativePositionList of operations
std::string s = GetInputName();
for(uint i=0; i<mArgsInfoList.size(); i++) {
+ // clitk::PrintMemory(true, "Start");
std::string text = "["+s+"] limits ";
if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
relPosFilter->Update();
m_working_input = relPosFilter->GetOutput();
StopCurrentStep<ImageType>(m_working_input);
+ // clitk::PrintMemory(true, "End");
}
}
//--------------------------------------------------------------------
<rect>
<x>0</x>
<y>0</y>
- <width>301</width>
- <height>480</height>
+ <width>411</width>
+ <height>534</height>
</rect>
</property>
<property name="sizePolicy">
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::AllEditTriggers</set>
+ </property>
+ <property name="tabKeyNavigation">
+ <bool>true</bool>
+ </property>
<property name="alternatingRowColors">
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
<string>Color</string>
</property>
</column>
+ <column>
+ <property name="text">
+ <string>Depth</string>
+ </property>
+ </column>
<item>
<property name="text">
<string>10</string>
<property name="text">
<string>Red</string>
</property>
+ <property name="text">
+ <string/>
+ </property>
</item>
</widget>
</item>
<string>Selected ROI</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>1</number>
- </property>
- <property name="margin">
- <number>1</number>
- </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
</item>
<item>
<widget class="QSlider" name="mOpacitySlider">
+ <property name="maximum">
+ <number>100</number>
+ </property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="mOpacitySpinBox"/>
+ <widget class="QSpinBox" name="mOpacitySpinBox">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ </widget>
</item>
</layout>
</item>
<number>1</number>
</property>
<property name="maximum">
- <number>5</number>
+ <number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
- <widget class="QLabel" name="mROInameLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Name : Lung</string>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="mROInameLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Name : Lung</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="mROInameLabel_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Depth</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="mDepthSpinBox">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999999</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</widget>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
- <x>344</x>
- <y>381</y>
+ <x>219</x>
+ <y>385</y>
</hint>
<hint type="destinationlabel">
- <x>426</x>
- <y>381</y>
+ <x>376</x>
+ <y>376</y>
</hint>
</hints>
</connection>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
- <x>432</x>
- <y>386</y>
+ <x>376</x>
+ <y>367</y>
</hint>
<hint type="destinationlabel">
- <x>351</x>
- <y>386</y>
+ <x>222</x>
+ <y>373</y>
</hint>
</hints>
</connection>
mForegroundValue = 1;
mBackgroundValue = 0;
m_modeBG = true;
+ mDepth = 1.0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-void vvBinaryImageOverlayActor::UpdateSlice(int slicer, int slice)
+void vvBinaryImageOverlayActor::UpdateSlice(int slicer, int slice, bool force)
{
if (!mSlicer) return;
- if (mPreviousSlice == mSlicer->GetSlice()) {
- if (mPreviousTSlice == mSlicer->GetTSlice()) {
- //DD("=========== NOTHING");
- return; // Nothing to do
+ if (!force) {
+ if (mPreviousSlice == mSlicer->GetSlice()) {
+ if (mPreviousTSlice == mSlicer->GetTSlice()) {
+ return; // Nothing to do
+ }
}
}
int orientation = mSlicer->GetOrientation();
int maskExtent[6];
ComputeExtent(orientation, mSlice, imageExtent, maskExtent);
- //ComputeExtent(imageExtent, maskExtent, mSlicer->GetImage()->GetFirstVTKImageData(), mImage->GetFirstVTKImageData());
ComputeExtent(maskExtent, maskExtent, mSlicer->GetImage()->GetFirstVTKImageData(), mImage->GetFirstVTKImageData());
- // std::cout << "maskExtent = " << maskExtent[0] << " " << maskExtent[1] << " " << maskExtent[2] << " "
- // << maskExtent[3] << " " << maskExtent[4] << " " << maskExtent[5] << std::endl;
mSlicer->ClipDisplayedExtent(maskExtent, mMapperList[mTSlice]->GetInput()->GetWholeExtent());
- // std::cout << "maskExtent = " << maskExtent[0] << " " << maskExtent[1] << " " << maskExtent[2] << " "
- // << maskExtent[3] << " " << maskExtent[4] << " " << maskExtent[5] << std::endl;
- SetDisplayExtentAndCameraPosition(orientation, mSlice, maskExtent, mImageActorList[mTSlice], 0.0);
+ SetDisplayExtentAndCameraPosition(orientation, mSlice, maskExtent, mImageActorList[mTSlice], mDepth);
// set previous slice
mPreviousTSlice = mSlicer->GetTSlice();
//----------------------------------------------------------------------------
void vvBinaryImageOverlayActor::ComputeExtent(int * inExtent, int * outExtent, vtkImageData * image, vtkImageData * overlay)
{
- outExtent[0] = (( image->GetOrigin()[0] + inExtent[0]*image->GetSpacing()[0] ) - overlay->GetOrigin()[0]) /
- overlay->GetSpacing()[0];
- outExtent[1] = (( image->GetOrigin()[0] + inExtent[1]*image->GetSpacing()[0] ) - overlay->GetOrigin()[0]) /
- overlay->GetSpacing()[0];
- outExtent[2] = (( image->GetOrigin()[1] + inExtent[2]*image->GetSpacing()[1] ) - overlay->GetOrigin()[1]) /
- overlay->GetSpacing()[1];
- outExtent[3] = (( image->GetOrigin()[1] + inExtent[3]*image->GetSpacing()[1] ) - overlay->GetOrigin()[1]) /
- overlay->GetSpacing()[1];
- outExtent[4] = (( image->GetOrigin()[2] + inExtent[4]*image->GetSpacing()[2] ) - overlay->GetOrigin()[2]) /
- overlay->GetSpacing()[2];
- outExtent[5] = (( image->GetOrigin()[2] + inExtent[5]*image->GetSpacing()[2] ) - overlay->GetOrigin()[2]) /
- overlay->GetSpacing()[2];
+ outExtent[0] = (int)lrint(((image->GetOrigin()[0] + inExtent[0]*image->GetSpacing()[0]) - overlay->GetOrigin()[0]) / overlay->GetSpacing()[0]);
+ outExtent[1] = (int)lrint(((image->GetOrigin()[0] + inExtent[1]*image->GetSpacing()[0]) - overlay->GetOrigin()[0]) / overlay->GetSpacing()[0]);
+ outExtent[2] = (int)lrint(((image->GetOrigin()[1] + inExtent[2]*image->GetSpacing()[1]) - overlay->GetOrigin()[1]) / overlay->GetSpacing()[1]);
+ outExtent[3] = (int)lrint(((image->GetOrigin()[1] + inExtent[3]*image->GetSpacing()[1]) - overlay->GetOrigin()[1]) / overlay->GetSpacing()[1]);
+ outExtent[4] = (int)lrint(((image->GetOrigin()[2] + inExtent[4]*image->GetSpacing()[2]) - overlay->GetOrigin()[2]) / overlay->GetSpacing()[2]);
+ outExtent[5] = (int)lrint(((image->GetOrigin()[2] + inExtent[5]*image->GetSpacing()[2]) - overlay->GetOrigin()[2]) / overlay->GetSpacing()[2]);
}
//----------------------------------------------------------------------------
vtkImageActor * actor,
double position)
{
+ /* FIXME
+ Error according to camera orientation
+ */
+
// Set position
if (orientation == vtkImageViewer2::SLICE_ORIENTATION_XY) {
- if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice)
- actor->SetPosition(0,0, position);
- else
+ //if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice)
actor->SetPosition(0,0, -position);
+ //else
+ //actor->SetPosition(0,0, position);
}
if (orientation == vtkImageViewer2::SLICE_ORIENTATION_XZ) {
- if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice)
- actor->SetPosition(0,position,0);
- else
+ //if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice)
+ // actor->SetPosition(0,position,0);
+ //else
actor->SetPosition(0,-position,0);
}
if (orientation == vtkImageViewer2::SLICE_ORIENTATION_YZ) {
- if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice)
- actor->SetPosition(position,0, 0);
- else
+ //if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice)
+ // actor->SetPosition(position,0, 0);
+ //else
actor->SetPosition(-position,0, 0);
}
actor->SetDisplayExtent(extent);
void SetColor(double r, double g, double b);
void SetOpacity(double d);
void SetImage(vvImage * image, double bg, bool modeBG=true);
+ void SetDepth(double d) { mDepth = d; }
void Initialize(bool IsVisible=true);
void UpdateColor();
- void UpdateSlice(int slicer, int slice);
+ void UpdateSlice(int slicer, int slice, bool force=false);
void HideActors();
void ShowActors();
double mForegroundValue;
bool m_modeBG;
vtkSmartPointer<vtkLookupTable> mColorLUT;
+ double mDepth;
std::vector<vtkSmartPointer<vtkImageMapToRGBA> > mMapperList;
std::vector<vtkSmartPointer<vtkImageActor> > mImageActorList;
mDisplayModeIsPreserveMemory = true;
SetPreserveMemoryModeEnabled(true);
mPreviousOrientation = -1;
+ mDepth = 1.0;
}
//------------------------------------------------------------------------------
vtkMarchingSquares * squares,
vtkImageClip * clipper,
double threshold, int orientation, int slice) {
-
- // Set parameter for the MarchigSquare
+ // Set parameter for the MarchigSquare
squares->SetValue(0, threshold);
// Get image extent
s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[orientation]; // from corner second image
s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[orientation]; // in voxel
- if (s == floor(s)) {
- extent2[orientation*2] = extent2[orientation*2+1] = (int)floor(s);
- } else {
- extent2[orientation*2] = (int)floor(s);
- extent2[orientation*2+1] = extent2[orientation*2];
- }
+ // Rint to the closest slice
+ extent2[orientation*2+1] = extent2[orientation*2] = (int)lrint(s);
// Do not display a contour if there is no contour on this slice
- if (extent2[orientation*2+1] > extent3[orientation*2+1]) {
+ // DD(extent2[orientation*2+1]);
+ // DD(extent3[orientation*2+1]);
+ // DD(extent2[orientation*2]);
+ // DD(extent3[orientation*2]);
+ if ((extent2[orientation*2+1] > extent3[orientation*2+1]) ||
+ (extent2[orientation*2] < extent3[orientation*2])) {
actor->VisibilityOff();
return;
}
// Move the actor to be visible
double position[3] = {0, 0, 0};
- position[orientation] = -1;
+ position[orientation] = -mDepth;
actor->SetPosition(position);
mapper->Update();
void SetLineWidth(double w);
void SetImage(vvImage * image);
void SetPreserveMemoryModeEnabled(bool b);
+ void SetDepth(double d) { mDepth = d; }
protected:
vvSlicer * mSlicer;
bool mHiddenImageIsUsed;
vvImage * mHiddenImage;
bool mDisplayModeIsPreserveMemory;
+ double mDepth;
// For preserveMemory mode
std::vector<vtkSmartPointer<vtkActor> > mSquaresActorList;
void vvMeshActor::SetCutSlice(double slice)
{
+ DD("SetCutSlice");
+ DD(slice);
mCutSlice=slice;
vtkImageData* mask;
if (static_cast<unsigned int>(mTimeSlice)<mMesh->GetNumberOfMasks())
mContourWidth = 1;
mContourColor.resize(3);
m_modeBG = true;
+ mDepth = 1.0;
}
//------------------------------------------------------------------------------
{
mOverlayActors.clear();
mImageContour.clear();
- Initialize(mIsVisible);
+ Initialize(mDepth, mIsVisible);
Update(); // No Render
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-void vvROIActor::Initialize(bool IsVisible) {
+void vvROIActor::Initialize(double depth, bool IsVisible) {
if (mROI->GetImage()) {
mImageContour.clear();
mOverlayActors.clear();
+ mDepth = depth;
for(int i=0; i<mSlicerManager->GetNumberOfSlicers(); i++) {
mImageContour.push_back(vvImageContour::New());
mImageContour[i]->SetColor(mContourColor[0], mContourColor[1], mContourColor[2]);
mImageContour[i]->SetLineWidth(mContourWidth);
mImageContour[i]->SetPreserveMemoryModeEnabled(true);
+ mImageContour[i]->SetDepth(mDepth);
//mImageContour[i]->SetPreserveMemoryModeEnabled(false); // SEG FAULT !!!
mImageContour[i]->SetSlicer(mSlicerManager->GetSlicer(i));
mImageContour[i]->HideActors();
mROI->GetDisplayColor()[2]);
mOverlayActors[i]->SetOpacity(mOpacity);
mOverlayActors[i]->SetSlicer(mSlicerManager->GetSlicer(i));
- mOverlayActors[i]->Initialize(IsVisible);
+ mOverlayActors[i]->Initialize(IsVisible);
+ mOverlayActors[i]->SetDepth(mDepth);
}
connect(mSlicerManager,SIGNAL(UpdateSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
//------------------------------------------------------------------------------
-void vvROIActor::Update()
+void vvROIActor::SetDepth(double d)
+{
+ mDepth = d;
+ for(int i=0; i<mSlicerManager->GetNumberOfSlicers(); i++) {
+ mOverlayActors[i]->SetDepth(d);
+ mImageContour[i]->SetDepth(d);
+ }
+ Update(true);
+}
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvROIActor::Update(bool force)
{
for(int i=0; i<mSlicerManager->GetNumberOfSlicers(); i++) {
- UpdateSlice(i, mSlicerManager->GetSlicer(i)->GetSlice());
+ UpdateSlice(i, mSlicerManager->GetSlicer(i)->GetSlice(), force);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-void vvROIActor::UpdateSlice(int slicer, int slices)
+void vvROIActor::UpdateSlice(int slicer, int slices, bool force)
{
if (!mROI->GetImage()) return;
if ((!mIsVisible) && (!mIsContourVisible)) return;
}
// Refresh overlays
- mOverlayActors[slicer]->UpdateSlice(slicer, slices);
+ mOverlayActors[slicer]->UpdateSlice(slicer, slices, force);
}
//------------------------------------------------------------------------------
void SetROI(clitk::DicomRT_ROI * r);
clitk::DicomRT_ROI * GetROI() { return mROI; }
void SetSlicerManager(vvSlicerManager * s);
- void Update();
- void Initialize(bool IsVisible=true);
+ void Update(bool force=false);
+ void Initialize(double d=1.0, bool IsVisible=true);
void SetVisible(bool b);
void SetContourVisible(bool b);
bool IsVisible();
void SetContourColor(double r, double v, double b);
std::vector<double> & GetContourColor();
void SetBGMode(bool b) { m_modeBG = b; }
+ void SetDepth(double d);
+ double GetDepth() { return mDepth; }
public slots:
- void UpdateSlice(int slicer, int slices);
+ void UpdateSlice(int slicer, int slices, bool force=false);
void UpdateColor();
void UpdateImage();
int mContourWidth;
std::vector<double> mContourColor;
bool m_modeBG;
+ double mDepth;
}; // end class vvROIActor
//------------------------------------------------------------------------------
actor->SetBGMode(modeBG);
actor->SetROI(roi);
actor->SetSlicerManager(mSlicerManager);
- actor->Initialize();
+ actor->Initialize(n+1); // depth is n+1 to start at 1
mMapROIIndex[n] = mROIActors.size()-1;
}
//------------------------------------------------------------------------------
connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
+ connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
connect(mReloadButton, SIGNAL(clicked()), this, SLOT(ReloadCurrentROI()));
connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
QTreeWidgetItem * w = mTreeWidgetList.back().data();
w->setText(0, QString("%1").arg(roi->GetROINumber()));
w->setText(1, QString("%1").arg(roi->GetName().c_str()));
+ vvROIActor * actor = mStructureSetActorsList[0]->GetROIActor(roi->GetROINumber());
+ w->setText(3, QString("%1").arg(actor->GetDepth()));
QBrush brush(QColor(roi->GetDisplayColor()[0]*255, roi->GetDisplayColor()[1]*255, roi->GetDisplayColor()[2]*255));
brush.setStyle(Qt::SolidPattern);
w->setBackground(2, brush);
mCurrentROI = roi;
mCurrentROIActor = actor;
+ // Warning -> avoid unuseful Render here by disconnect slider
// Update GUI
+ disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
+ disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
+ disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
+ disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
+ disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
+ disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
+ disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
+ disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
+
mGroupBoxROI->setEnabled(true);
mROInameLabel->setText(roi->GetName().c_str());
mCheckBoxShow->setChecked(actor->IsVisible());
mContourCheckBoxShow->setChecked(actor->IsContourVisible());
mContourWidthSpinBox->setValue(actor->GetContourWidth());
-
- // Warning -> avoir unuseful Render here by disconnect slider
- disconnect(mOpacitySlider, SIGNAL(valueChanged(int)),
- this, SLOT(OpacityChanged(int)));
+ mDepthSpinBox->setValue(actor->GetDepth());
+ w->setText(3, QString("%1").arg(actor->GetDepth()));
mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
- connect(mOpacitySlider, SIGNAL(valueChanged(int)),
- this, SLOT(OpacityChanged(int)));
- actor->Update();
+ connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
+ connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
+ connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
+ connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
+ connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
+ connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
+ connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
+ connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
+
+ // is this needed ?
+ // actor->Update();
// Final rendering
- mCurrentSlicerManager->Render();
+ // mCurrentSlicerManager->Render();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void vvToolStructureSetManager::ChangeDepth(int n) {
+ mCurrentROIActor->SetDepth(n);
+ mCurrentROIActor->UpdateImage();
+ mCurrentSlicerManager->Render();
+ QList<QTreeWidgetItem *> l = mTree->selectedItems();
+ QTreeWidgetItem * w = l[0];
+ w->setText(3, QString("%1").arg(mCurrentROIActor->GetDepth()));
+}
+//------------------------------------------------------------------------------
+
+
//------------------------------------------------------------------------------
void vvToolStructureSetManager::ReloadCurrentROI() {
// Reload image
void ChangeColor();
void ChangeContourColor();
void ChangeContourWidth(int n);
+ void ChangeDepth(int n);
void AllVisibleROIToggled(int b);
void AllVisibleContourROIToggled(bool b);
void ReloadCurrentROI();