From 163fa80ef3873595f3e3cf75fb03e53536d1a6ee Mon Sep 17 00:00:00 2001 From: dsarrut Date: Fri, 2 Apr 2010 09:46:58 +0000 Subject: [PATCH] - correct crop 2D bug - prepare for DicomRT Struct --- common/CMakeLists.txt | 8 + common/clitkCommonGenericFilter.h | 3 + common/clitkDicomRT_Contour.cxx | 121 ++++++++ common/clitkDicomRT_Contour.h | 85 ++++++ common/clitkDicomRT_ROI.cxx | 150 ++++++++++ common/clitkDicomRT_ROI.h | 61 ++++ .../clitkDicomRT_ROI_ConvertToImageFilter.cxx | 191 ++++++++++++ .../clitkDicomRT_ROI_ConvertToImageFilter.h | 58 ++++ common/clitkDicomRT_StructureSet.cxx | 239 +++++++++++++++ common/clitkDicomRT_StructureSet.h | 68 +++++ vv/CMakeLists.txt | 11 +- vv/vvImageContour.cxx | 280 +++++++++++++++++- vv/vvImageContour.h | 28 ++ vv/vvMainWindow.cxx | 3 +- vv/vvSlicerManager.cxx | 5 + vv/vvToolCropImage.cxx | 6 +- vv/vvToolImageArithm.cxx | 2 +- 17 files changed, 1302 insertions(+), 17 deletions(-) create mode 100644 common/clitkDicomRT_Contour.cxx create mode 100644 common/clitkDicomRT_Contour.h create mode 100644 common/clitkDicomRT_ROI.cxx create mode 100644 common/clitkDicomRT_ROI.h create mode 100644 common/clitkDicomRT_ROI_ConvertToImageFilter.cxx create mode 100644 common/clitkDicomRT_ROI_ConvertToImageFilter.h create mode 100644 common/clitkDicomRT_StructureSet.cxx create mode 100644 common/clitkDicomRT_StructureSet.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index e40a81f..ef102d9 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -32,5 +32,13 @@ SET(clitkCommon_SRC ADD_LIBRARY(clitkCommon STATIC ${clitkCommon_SRC}) + +ADD_LIBRARY(clitkDicomRTStruct STATIC + clitkDicomRT_Contour.cxx + clitkDicomRT_ROI.cxx + clitkDicomRT_StructureSet.cxx + clitkDicomRT_ROI_ConvertToImageFilter.cxx +) + #ADD_LIBRARY(clitkCommonShared SHARED ${clitkCommon_SRC}) #SET_TARGET_PROPERTIES(clitkCommonShared PROPERTIES COMPILE_FLAGS -fPIC) diff --git a/common/clitkCommonGenericFilter.h b/common/clitkCommonGenericFilter.h index 55d2f94..3f9d63c 100644 --- a/common/clitkCommonGenericFilter.h +++ b/common/clitkCommonGenericFilter.h @@ -15,8 +15,10 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html ======================================================================-====*/ + #ifndef CLITKCOMMONGENERICFILTER_H #define CLITKCOMMONGENERICFILTER_H + #include "clitkCommon.h" /*-------------------------------------------------------------------- @@ -32,6 +34,7 @@ namespace clitk { class GenericFilterFunctorBase { public: GenericFilterFunctorBase(FilterType * f) { mFilter = f; } + virtual ~GenericFilterFunctorBase() { delete mFilter; } virtual void Execute()= 0; FilterType * mFilter; }; diff --git a/common/clitkDicomRT_Contour.cxx b/common/clitkDicomRT_Contour.cxx new file mode 100644 index 0000000..ac6d441 --- /dev/null +++ b/common/clitkDicomRT_Contour.cxx @@ -0,0 +1,121 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#include "clitkDicomRT_Contour.h" +#include + +//-------------------------------------------------------------------- +clitk::DicomRT_Contour::DicomRT_Contour() { + mMeshIsUpToDate = false; + mNbOfPoints = 0; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +clitk::DicomRT_Contour::~DicomRT_Contour() { + +} +//-------------------------------------------------------------------- + + + +//-------------------------------------------------------------------- +void clitk::DicomRT_Contour::Print(std::ostream & os) const { + DD("TODO : print Contours"); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +bool clitk::DicomRT_Contour::Read(gdcm::SQItem * item) { + + // Contour type [Contour Geometric Type] + mType = item->GetEntryValue(0x3006,0x0042); + // DD(mType); + if (mType != "CLOSED_PLANAR ") { ///WARNING to the space after the name ... + std::cerr << "Skip this contour : type=" << mType << std::endl; + return false; + } + + // Number of points [Number of Contour Points] + mNbOfPoints = parse_value(item->GetEntryValue(0x3006,0x0046)); + // DD(mNbOfPoints); + + // Read values [Contour Data] + std::vector points = parse_string(item->GetEntryValue(0x3006,0x0050),'\\'); + assert(points.size() == static_cast(mNbOfPoints)*3); + + // Organize values + mData = vtkPoints::New(); + mData->SetDataTypeToDouble(); + mData->SetNumberOfPoints(mNbOfPoints); + double z = -1; + for(unsigned int i=0; iSetPoint(i, p); + if (z == -1) z = p[2]; + if (p[2] != z) { + DD(i); + DD(p[2]); + DD(z); + std::cout << "ERROR ! contour not in the same slice" << std::endl; + assert(p[2] == z); + } + } + + return true; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +vtkPolyData * clitk::DicomRT_Contour::GetMesh() { + if (!mMeshIsUpToDate) { + ComputeMesh(); + } + return mMesh; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_Contour::ComputeMesh() { + // DD("ComputeMesh Contour"); + mMesh = vtkPolyData::New(); + mMesh->Allocate(); //for cell structures + mMesh->SetPoints(vtkPoints::New()); + vtkIdType ids[2]; + for (unsigned int idx=0 ; idxGetPoints()->InsertNextPoint(mData->GetPoint(idx)[0], + mData->GetPoint(idx)[1], + mData->GetPoint(idx)[2]); + ids[0]=idx; + ids[1]=(ids[0]+1) % mNbOfPoints; //0-1,1-2,...,n-1-0 + // DD(ids[0]); +// DD(ids[1]); + mMesh->GetLines()->InsertNextCell(2,ids); + } + // DD(mMesh->GetNumberOfCells()); + mMeshIsUpToDate = true; +} +//-------------------------------------------------------------------- diff --git a/common/clitkDicomRT_Contour.h b/common/clitkDicomRT_Contour.h new file mode 100644 index 0000000..b599769 --- /dev/null +++ b/common/clitkDicomRT_Contour.h @@ -0,0 +1,85 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#ifndef CLITKDICOMRT_CONTOUR_H +#define CLITKDICOMRT_CONTOUR_H + +#include "clitkCommon.h" +#include "clitkDicomRT_Contour.h" +#include +#include +#include +#include + +namespace clitk { + + //-------------------------------------------------------------------- + class DicomRT_Contour { + + public: + DicomRT_Contour(); + ~DicomRT_Contour(); + + void Print(std::ostream & os = std::cout) const; + bool Read(gdcm::SQItem * item); + vtkPolyData * GetMesh(); + + protected: + void ComputeMesh(); + unsigned int mNbOfPoints; + std::string mType; + vtkPoints * mData; + vtkPolyData * mMesh; + bool mMeshIsUpToDate; + + }; + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + template + ElementType parse_value(std::string str) + { + std::istringstream parser(str); + ElementType value; + parser >> value; + if (parser.fail()) { + DD(str); + DD(value); + } + assert(!parser.fail()); + return value; + } + + template + std::vector parse_string(std::string str,char delim) { + std::istringstream ss(str); + std::string token; + std::vector result; + while (getline(ss,token,delim)) + { + result.push_back(parse_value(token)); + } + return result; + } + //-------------------------------------------------------------------- + + +} // end namespace clitk +#endif // CLITKDICOMRT_CONTOUR_H + diff --git a/common/clitkDicomRT_ROI.cxx b/common/clitkDicomRT_ROI.cxx new file mode 100644 index 0000000..f65dc62 --- /dev/null +++ b/common/clitkDicomRT_ROI.cxx @@ -0,0 +1,150 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#include "clitkDicomRT_ROI.h" +#include +#include + +//-------------------------------------------------------------------- +clitk::DicomRT_ROI::DicomRT_ROI() { + mName = "NoName"; + mNumber = -1; + mColor.resize(3); + mColor[0] = mColor[1] = mColor[2] = 0; + mMeshIsUpToDate = false; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +clitk::DicomRT_ROI::~DicomRT_ROI() { + +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +int clitk::DicomRT_ROI::GetROINumber() const { + return mNumber; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_ROI::GetName() const { + return mName; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::vector & clitk::DicomRT_ROI::GetDisplayColor() const { + return mColor; +} +//-------------------------------------------------------------------- + + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI::Print(std::ostream & os) const { + os << "ROI " << mNumber << "\t" << mName + << "\t(" << mColor[0] << " " << mColor[1] << " " << mColor[2] << ")" + << "\t Contours = " << mListOfContours.size() << std::endl; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI::Read(std::map & rois, gdcm::SQItem * item) { + + // Change number if needed + + // TODO + + // ROI number [Referenced ROI Number] + mNumber = atoi(item->GetEntryValue(0x3006,0x0084).c_str()); + + // Retrieve ROI Name + mName = rois[mNumber]; + + // ROI Color [ROI Display Color] + mColor = clitk::parse_string(item->GetEntryValue(0x3006,0x002a),'\\'); + + // Read contours [Contour Sequence] + gdcm::SeqEntry * contours=item->GetSeqEntry(0x3006,0x0040); + for(gdcm::SQItem* j=contours->GetFirstSQItem();j!=0;j=contours->GetNextSQItem()) { + DicomRT_Contour * c = new DicomRT_Contour; + bool b = c->Read(j); + if (b) mListOfContours.push_back(c); + } +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +vtkPolyData * clitk::DicomRT_ROI::GetMesh() { + if (!mMeshIsUpToDate) { + ComputeMesh(); + } + return mMesh; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI::ComputeMesh() { + vtkAppendPolyData * append = vtkAppendPolyData::New(); + for(unsigned int i=0; iAddInput(mListOfContours[i]->GetMesh()); + } + append->Update(); + mMesh = append->GetOutput(); + mMeshIsUpToDate = true; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI::SetFromBinaryImage(vvImage::Pointer image, int n, + std::string name, + std::vector color) { + + // ROI number [Referenced ROI Number] + mNumber = n; + + // ROI Name + mName = name; + + // ROI Color [ROI Display Color] + mColor = color; + + // No contours [Contour Sequence] + mListOfContours.clear(); + + // Set image + mImage = image; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const vvImage::Pointer clitk::DicomRT_ROI::GetImage() const { + return mImage; +} +//-------------------------------------------------------------------- diff --git a/common/clitkDicomRT_ROI.h b/common/clitkDicomRT_ROI.h new file mode 100644 index 0000000..fe95208 --- /dev/null +++ b/common/clitkDicomRT_ROI.h @@ -0,0 +1,61 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#ifndef CLITKDICOMRT_ROI_H +#define CLITKDICOMRT_ROI_H + +#include "clitkDicomRT_Contour.h" +#include "vvImage.h" + +namespace clitk { + + //-------------------------------------------------------------------- + class DicomRT_ROI { + + public: + DicomRT_ROI(); + ~DicomRT_ROI(); + + void Print(std::ostream & os = std::cout) const; + void Read(std::map & rois, gdcm::SQItem * item); + void SetFromBinaryImage(vvImage::Pointer image, int n, + std::string name, + std::vector color); + + int GetROINumber() const; + const std::string & GetName() const; + const std::vector & GetDisplayColor() const; + vtkPolyData * GetMesh(); + const vvImage::Pointer GetImage() const; + + protected: + void ComputeMesh(); + std::string mName; + int mNumber; + std::vector mColor; + std::vector mListOfContours; + vtkPolyData * mMesh; + bool mMeshIsUpToDate; + vvImage::Pointer mImage; + }; + //-------------------------------------------------------------------- + +} // end namespace clitk +#endif // CLITKDICOMRT_ROI_H + diff --git a/common/clitkDicomRT_ROI_ConvertToImageFilter.cxx b/common/clitkDicomRT_ROI_ConvertToImageFilter.cxx new file mode 100644 index 0000000..ef5ecb4 --- /dev/null +++ b/common/clitkDicomRT_ROI_ConvertToImageFilter.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#include "clitkDicomRT_ROI_ConvertToImageFilter.h" +#include +#include +#include +#include +#include +#include "clitkImageCommon.h" + +//-------------------------------------------------------------------- +clitk::DicomRT_ROI_ConvertToImageFilter::DicomRT_ROI_ConvertToImageFilter() { + mROI = NULL; + mImageInfoIsSet = false; + mWriteOutput = false; + mCropMask = true; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +clitk::DicomRT_ROI_ConvertToImageFilter::~DicomRT_ROI_ConvertToImageFilter() { + +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI_ConvertToImageFilter::SetROI(clitk::DicomRT_ROI * roi) { + mROI = roi; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI_ConvertToImageFilter::SetCropMaskEnabled(bool b) { + mCropMask = b; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI_ConvertToImageFilter::SetOutputImageFilename(std::string s) { + mOutputFilename = s; + mWriteOutput = true; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI_ConvertToImageFilter::SetImageFilename(std::string f) { + itk::ImageIOBase::Pointer header = clitk::readImageHeader(f); + if (header->GetNumberOfDimensions() < 3) { + std::cerr << "Error. Please provide a 3D image instead of " << f << std::endl; + exit(0); + } + if (header->GetNumberOfDimensions() > 3) { + std::cerr << "Warning dimension > 3 are ignored" << std::endl; + } + mSpacing.resize(3); + mOrigin.resize(3); + mSize.resize(3); + for(unsigned int i=0; i<3; i++) { + mSpacing[i] = header->GetSpacing(i); + mOrigin[i] = header->GetOrigin(i); + mSize[i] = header->GetDimensions(i); + } + mImageInfoIsSet = true; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_ROI_ConvertToImageFilter::Update() { + if (!mROI) { + std::cerr << "Error. No ROI set, please use SetROI." << std::endl; + exit(0); + } + if (!mImageInfoIsSet) { + std::cerr << "Error. Please provide image info (spacing/origin) with SetImageFilename" << std::endl; + exit(0); + } + // DD("Update"); + + // Get Mesh + vtkPolyData * mesh = mROI->GetMesh(); + DD(mesh->GetNumberOfCells()); + + // Get bounds + double *bounds=mesh->GetBounds(); + // for(int i=0; i<6; i++){ +// DD(bounds[i]); +// } + + // Compute origin + std::vector origin; + origin.resize(3); + origin[0] = floor((bounds[0]-mOrigin[0])/mSpacing[0]-2)*mSpacing[0]+mOrigin[0]; + origin[1] = floor((bounds[2]-mOrigin[1])/mSpacing[1]-2)*mSpacing[1]+mOrigin[1]; + origin[2] = floor((bounds[4]-mOrigin[2])/mSpacing[2]-2)*mSpacing[2]+mOrigin[2]; + + // Compute extend + std::vector extend; + extend.resize(3); + extend[0] = ceil((bounds[1]-origin[0])/mSpacing[0]+4); + extend[1] = ceil((bounds[3]-origin[1])/mSpacing[1]+4); + extend[2] = ceil((bounds[5]-origin[2])/mSpacing[2]+4); + + // If no crop, set initial image size/origin + if (!mCropMask) { + for(int i=0; i<3; i++) { + origin[i] = mOrigin[i]; + extend[i] = mSize[i]-1; + } + } + + // Create new output image + mBinaryImage = vtkImageData::New(); + mBinaryImage->SetScalarTypeToUnsignedChar(); + mBinaryImage->SetOrigin(&origin[0]); + mBinaryImage->SetSpacing(&mSpacing[0]); + mBinaryImage->SetExtent(0, extend[0], + 0, extend[1], + 0, extend[2]); + mBinaryImage->AllocateScalars(); + + // for(int i=0; i<3; i++){ + // DD(origin[i]); + // DD(extend[i]); + // DD(mBinaryImage->GetDimensions()[i]); + // } + memset(mBinaryImage->GetScalarPointer(), 0, + mBinaryImage->GetDimensions()[0]*mBinaryImage->GetDimensions()[1]*mBinaryImage->GetDimensions()[2]*sizeof(unsigned char)); + + // Extrude + vtkSmartPointer extrude=vtkSmartPointer::New(); + extrude->SetInput(mesh); + ///We extrude in the -slice_spacing direction to respect the FOCAL convention // ????????????? + extrude->SetVector(0, 0, -mSpacing[2]); + + // Binarization + vtkSmartPointer sts=vtkSmartPointer::New(); + //The following line is extremely important + //http://www.nabble.com/Bug-in-vtkPolyDataToImageStencil--td23368312.html#a23370933 + sts->SetTolerance(0); + sts->SetInformationInput(mBinaryImage); + sts->SetInput(extrude->GetOutput()); + //sts->SetInput(mesh); + + vtkSmartPointer stencil=vtkSmartPointer::New(); + stencil->SetStencil(sts->GetOutput()); + stencil->SetInput(mBinaryImage); + stencil->ReverseStencilOn(); + stencil->Update(); + mBinaryImage->ShallowCopy(stencil->GetOutput()); + + if (mWriteOutput) { + typedef itk::Image ImageType; + typedef itk::VTKImageToImageFilter ConnectorType; + ConnectorType::Pointer connector = ConnectorType::New(); + connector->SetInput(GetOutput()); + connector->Update(); + clitk::writeImage(connector->GetOutput(), mOutputFilename); + } +} +//-------------------------------------------------------------------- + + + +//-------------------------------------------------------------------- +vtkImageData * clitk::DicomRT_ROI_ConvertToImageFilter::GetOutput() { + return mBinaryImage; +} +//-------------------------------------------------------------------- diff --git a/common/clitkDicomRT_ROI_ConvertToImageFilter.h b/common/clitkDicomRT_ROI_ConvertToImageFilter.h new file mode 100644 index 0000000..d5d27b3 --- /dev/null +++ b/common/clitkDicomRT_ROI_ConvertToImageFilter.h @@ -0,0 +1,58 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#ifndef CLITKDICOMRT_ROI_CONVERTTOIMAGEFILTER_H +#define CLITKDICOMRT_ROI_CONVERTTOIMAGEFILTER_H + +#include "clitkDicomRT_ROI.h" +#include "clitkImageCommon.h" +#include + +namespace clitk { + + //-------------------------------------------------------------------- + class DicomRT_ROI_ConvertToImageFilter { + + public: + DicomRT_ROI_ConvertToImageFilter(); + ~DicomRT_ROI_ConvertToImageFilter(); + + void SetROI(clitk::DicomRT_ROI * roi); + void SetImageFilename(std::string s); + void SetOutputImageFilename(std::string s); + void Update(); + vtkImageData * GetOutput(); + void SetCropMaskEnabled(bool b); + + protected: + bool mImageInfoIsSet; + bool mWriteOutput; + bool mCropMask; + std::string mOutputFilename; + std::vector mSpacing; + std::vector mOrigin; + std::vector mSize; + clitk::DicomRT_ROI * mROI; + vtkImageData * mBinaryImage; + }; + //-------------------------------------------------------------------- + +} // end namespace clitk +#endif // CLITKDICOMRT_ROI_CONVERTTOIMAGEFILTER_H + diff --git a/common/clitkDicomRT_StructureSet.cxx b/common/clitkDicomRT_StructureSet.cxx new file mode 100644 index 0000000..d7c4e79 --- /dev/null +++ b/common/clitkDicomRT_StructureSet.cxx @@ -0,0 +1,239 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#include "clitkDicomRT_StructureSet.h" +#include + +//-------------------------------------------------------------------- +clitk::DicomRT_StructureSet::DicomRT_StructureSet() { + mStudyID = "NoStudyID"; + mStudyTime = "NoStudyTime"; + mStudyDate = "NoStudyDate"; + mLabel = "NoLabel"; + mName = "NoName"; + mDate = "NoDate"; + mTime = "NoTime"; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +clitk::DicomRT_StructureSet::~DicomRT_StructureSet() { + +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetStudyID() const { + return mStudyID; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetStudyTime() const{ + return mStudyTime; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetStudyDate() const { + return mStudyDate; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetLabel() const { + return mLabel; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetName() const { + return mName; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetDate() const { + return mDate; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::string & clitk::DicomRT_StructureSet::GetTime() const { + return mTime; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +const std::vector & clitk::DicomRT_StructureSet::GetListOfROI() const { + return mListOfROI; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +clitk::DicomRT_ROI* clitk::DicomRT_StructureSet::GetROI(int n) { + if (mMapOfROIIndex.find(n) == mMapOfROIIndex.end()) { + std::cerr << "No ROI number " << n << std::endl; + return NULL; + } + DD(mListOfROI[mMapOfROIIndex[n]]->GetName()); + DD(mListOfROI[mMapOfROIIndex[n]]->GetROINumber()); + return mListOfROI[mMapOfROIIndex[n]]; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_StructureSet::Print(std::ostream & os) const { + os << "Study ID = " << mStudyID << std::endl + << "Study Date = " << mStudyDate << std::endl + << "Study Time = " << mStudyTime << std::endl + << "Struct Label = " << mLabel << std::endl + << "Struct Name = " << mName << std::endl + << "Struct Time = " << mTime << std::endl + << "Number of ROI = " << mListOfROI.size() << std::endl; + for(unsigned int i=0; iPrint(os); + } +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +void clitk::DicomRT_StructureSet::Read(const std::string & filename) { + // Open DICOM + gdcm::File reader; + reader.SetFileName(filename.c_str()); + reader.SetMaxSizeLoadEntry(16384); // Needed ... + reader.SetLoadMode(gdcm::LD_NOSHADOW); // don't load shadow tags (in order to save memory) + reader.Load(); + + // Check file type + //Verify if the file is a RT-Structure-Set dicom file + if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0016),"1.2.840.10008.5.1.4.1.1.481.3")) { //SOP clas UID + std::cerr << "Error. the file " << filename + << " is not a Dicom Struct ? (must have a SOP Class UID [0008|0016] = 1.2.840.10008.5.1.4.1.1.481.3 ==> [RT Structure Set Storage])" + << std::endl; + exit(0); + } + if (!gdcm::Util::DicomStringEqual(reader.GetEntryValue(0x0008,0x0060),"RTSTRUCT")) { //SOP clas UID + std::cerr << "Error. the file " << filename + << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])" + << std::endl; + exit(0); + } + + // Read global info + mStudyID = reader.GetValEntry(0x0020,0x0010)->GetValue(); + mStudyTime = reader.GetValEntry(0x008,0x0020)->GetValue(); + mStudyDate = reader.GetValEntry(0x008,0x0030)->GetValue(); + mLabel = reader.GetValEntry(0x3006,0x002)->GetValue(); + mName = reader.GetValEntry(0x3006,0x004)->GetValue(); + mTime = reader.GetValEntry(0x3006,0x009)->GetValue(); + + //---------------------------------- + // Read all ROI Names and number + // 0x3006,0x0020 = [ Structure Set ROI Sequence ] + gdcm::SeqEntry * roi_seq=reader.GetSeqEntry(0x3006,0x0020); + assert(roi_seq); // TODO error message + for (gdcm::SQItem* r=roi_seq->GetFirstSQItem();r!=0;r=roi_seq->GetNextSQItem()) { + std::string name = r->GetEntryValue(0x3006,0x0026); // 0x3006,0x0026 = [ROI Name] + int nb = atoi(r->GetEntryValue(0x3006,0x0022).c_str()); // 0x3006,0x0022 = [ROI Number] + // Change number if needed + + //TODO + + // Check if such a number already exist + if (mMapOfROIName.find(nb) != mMapOfROIName.end()) { + std::cerr << "WARNING. A Roi already exist with the number " + << nb << ". I replace." << std::endl; + } + // Add in map + mMapOfROIName[nb] = name; + } + // DD(mMapOfROIName.size()); + + //---------------------------------- + // Read all ROI + // 0x3006,0x0039 = [ ROI Contour Sequence ] + gdcm::SeqEntry * roi_contour_seq=reader.GetSeqEntry(0x3006,0x0039); + assert(roi_contour_seq); // TODO error message + int n=0; + for (gdcm::SQItem* r=roi_contour_seq->GetFirstSQItem();r!=0;r=roi_contour_seq->GetNextSQItem()) { + DicomRT_ROI * roi = new DicomRT_ROI; + roi->Read(mMapOfROIName, r); + mListOfROI.push_back(roi); + mMapOfROIIndex[roi->GetROINumber()] = n; + n++; + } + +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +int clitk::DicomRT_StructureSet::AddBinaryImageAsNewROI(vvImage::Pointer im, std::string n) { + DD("AddBinaryImageAsNewROI"); + // Search max ROI number + int max = -1; + for(unsigned int i=0; iGetROINumber() > max) + max = mListOfROI[i]->GetROINumber(); + } + DD(max); + ++max; + DD(max); + + // Compute name + std::ostringstream oss; + oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(n)) + << "_roi_" << max << vtksys::SystemTools::GetFilenameLastExtension(n); + DD(oss.str()); + mMapOfROIName[max] = oss.str(); + + // Set color + std::vector color; + color.push_back(1); + color.push_back(0); + color.push_back(0); + + // Create ROI + DicomRT_ROI * roi = new DicomRT_ROI; + roi->SetFromBinaryImage(im, + max, + oss.str(), + color); + mListOfROI.push_back(roi); + mMapOfROIIndex[mListOfROI.size()-1] = max; + DD(mMapOfROIIndex[mListOfROI.size()-1]); + return max; +} +//-------------------------------------------------------------------- + + diff --git a/common/clitkDicomRT_StructureSet.h b/common/clitkDicomRT_StructureSet.h new file mode 100644 index 0000000..77d164d --- /dev/null +++ b/common/clitkDicomRT_StructureSet.h @@ -0,0 +1,68 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + Main authors : XX XX XX + + Authors belongs to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + - BSD http://www.opensource.org/licenses/bsd-license.php + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + + =========================================================================*/ + +#ifndef CLITKDICOMRT_STRUCTURESET_H +#define CLITKDICOMRT_STRUCTURESET_H + +#include "clitkCommon.h" +#include "clitkDicomRT_ROI.h" +#include "vvImage.h" + +namespace clitk { + + //-------------------------------------------------------------------- + class DicomRT_StructureSet { + + public: + DicomRT_StructureSet(); + ~DicomRT_StructureSet(); + + void Print(std::ostream & os = std::cout) const; + void Read(const std::string & filename); + + const std::vector & GetListOfROI() const; + clitk::DicomRT_ROI * GetROI(int n); + const std::string & GetStudyID() const; + const std::string & GetStudyTime() const; + const std::string & GetStudyDate() const; + const std::string & GetLabel() const; + const std::string & GetName() const; + const std::string & GetDate() const; + const std::string & GetTime() const; + + int AddBinaryImageAsNewROI(vvImage::Pointer i, std::string name); + + protected: + std::string mStudyID; + std::string mStudyTime; + std::string mStudyDate; + std::string mLabel; + std::string mName; + std::string mDate; + std::string mTime; + std::map mMapOfROIName; + std::map mMapOfROIIndex; + std::vector mListOfROI; + + }; + //-------------------------------------------------------------------- + +} // end namespace clitk +#endif // CLITKDICOMRT_STRUCTURESET_H + diff --git a/vv/CMakeLists.txt b/vv/CMakeLists.txt index e8a5cd8..160fe69 100644 --- a/vv/CMakeLists.txt +++ b/vv/CMakeLists.txt @@ -42,6 +42,7 @@ endif(COMMAND cmake_policy) LINK_LIBRARIES ( #ITKIO clitkCommon + clitkDicomRTStruct #clitkGGO clitkFilters ${QT_QTCORE_LIBRARY} @@ -112,7 +113,9 @@ SET(vv_SRCS vvImageContour.cxx vvToolImageArithm.cxx vvToolConvert.cxx -# vvToolStructureSetManager.cxx + # vvToolStructureSetManager.cxx +# vvStructureSetActor.cxx +# vvROIActor.cxx ) QT4_WRAP_CPP(vv_SRCS @@ -144,7 +147,9 @@ QT4_WRAP_CPP(vv_SRCS vvToolCropImage.h vvToolImageArithm.h vvToolConvert.h -# vvToolStructureSetManager.h + # vvToolStructureSetManager.h + # vvStructureSetActor.h +# vvROIActor.h ) QT4_WRAP_UI(vv_UI_CXX @@ -171,7 +176,7 @@ QT4_WRAP_UI(vv_UI_CXX qt_ui/vvToolCropImage.ui qt_ui/vvToolBinarize.ui qt_ui/vvToolImageArithm.ui -# qt_ui/vvToolStructureSetManager.ui + # qt_ui/vvToolStructureSetManager.ui ) SET(vvUI_RCCS vvIcons.qrc) diff --git a/vv/vvImageContour.cxx b/vv/vvImageContour.cxx index a98247c..fa22d45 100644 --- a/vv/vvImageContour.cxx +++ b/vv/vvImageContour.cxx @@ -14,9 +14,10 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -======================================================================-====*/ + ======================================================================-====*/ #include "vvImageContour.h" +#include "vvImage.h" #include #include #include @@ -30,6 +31,8 @@ vvImageContour::vvImageContour() { mTSlice = -1; mSlice = 0; + mHiddenImageIsUsed = false; + mDisplayModeIsPreserveMemory = true; } //------------------------------------------------------------------------------ @@ -53,9 +56,11 @@ void vvImageContour::setSlicer(vvSlicer * slicer) { for (unsigned int numImage = 0; numImage < mSlicer->GetImage()->GetVTKImages().size(); numImage++) { vtkImageClip * mClipper = vtkImageClip::New(); vtkMarchingSquares * mSquares = vtkMarchingSquares::New(); - vtkPolyDataMapper * mSquaresMapper = vtkPolyDataMapper::New(); + // vtkPolyDataMapper * mSquaresMapper = vtkPolyDataMapper::New(); vtkActor * mSquaresActor = vtkActor::New(); + createNewActor(&mSquaresActor, &mSquares, &mClipper); + /* mClipper->SetInput(mSlicer->GetImage()->GetVTKImages()[numImage]); mSquares->SetInput(mClipper->GetOutput()); mSquaresMapper->SetInput(mSquares->GetOutput()); @@ -65,7 +70,7 @@ void vvImageContour::setSlicer(vvSlicer * slicer) { mSquaresActor->SetPickable(0); mSquaresActor->VisibilityOff(); mSlicer->GetRenderer()->AddActor(mSquaresActor); - + */ mSquaresActorList.push_back(mSquaresActor); mSquaresList.push_back(mSquares); mClipperList.push_back(mClipper); @@ -74,6 +79,37 @@ void vvImageContour::setSlicer(vvSlicer * slicer) { //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void vvImageContour::setImage(vvImage::Pointer image) { + DD("vvImageContour::setImage"); + for (unsigned int numImage = 0; numImage < image->GetVTKImages().size(); numImage++) { + mClipperList[numImage]->SetInput(image->GetVTKImages()[numImage]); + } + mHiddenImageIsUsed = true; + mHiddenImage = image; +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvImageContour::setPreserveModeEnabled(bool b) { + DD("setPreserveModeEnabled"); + DD(b); + DD(mDisplayModeIsPreserveMemory); + if (mDisplayModeIsPreserveMemory == b) return; + mDisplayModeIsPreserveMemory = b; + if (!b) { + initializeCacheMode(); + } + else { + for(unsigned int d=0; dGetSlice(); - // how to not update if not visible ? + if (mDisplayModeIsPreserveMemory) { + updateWithPreserveMemoryMode(); + } + else { + updateWithFastCacheMode(); + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvImageContour::updateWithPreserveMemoryMode() { - mSlice = mSlicer->GetSlice(); // Only change actor visibility if tslice change if (mTSlice != mSlicer->GetTSlice()) { if (mTSlice != -1) @@ -126,13 +175,78 @@ void vvImageContour::update(double value) { vtkMarchingSquares * mSquares = mSquaresList[mTSlice]; vtkImageClip * mClipper = mClipperList[mTSlice]; vtkActor * mSquaresActor = mSquaresActorList[mTSlice]; + int orientation = computeCurrentOrientation(); + // DD(orientation); + + updateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice); + return; + // Do it - mSquares->SetValue(0,value); + mSquares->SetValue(0, mValue ); int* extent = mSlicer->GetImageActor()->GetDisplayExtent(); - mClipper->SetOutputWholeExtent(extent[0],extent[1],extent[2], - extent[3],extent[4],extent[5]); + // DD(extent[0]); + // DD(extent[1]); + // DD(extent[2]); + // DD(extent[3]); + // DD(extent[4]); + // DD(extent[5]); + + // int* extent2 = mClipper->GetInput()->GetDisplayExtent(); + // DD(extent2[0]); + // DD(extent2[1]); + int* extent2 = new int[6]; + if (mHiddenImageIsUsed) { + int * extent3; + extent3 = mHiddenImage->GetFirstVTKImageData()->GetExtent(); + for(int i=0; i<6; i++) extent2[i] = extent3[i]; + // DD(extent2[0]); + // DD(extent2[1]); + // DD(extent2[2]); + // DD(extent2[3]); + // DD(extent2[4]); + // DD(extent2[5]); + for(int i=0; i<6; i+=2) { + if (extent[i] != extent[i+1]) { + // extent[i] = extent2[i]; + // extent[i+1] = extent2[i+1]; + } + else { + // DD(extent[i]); + // DD(mSlicer->GetImage()->GetSpacing()[i/2]); + // DD(mHiddenImage->GetFirstVTKImageData()->GetSpacing()[i/2]); + + double s = (double)extent[i]*(double)mSlicer->GetImage()->GetSpacing()[i/2]; // in mm + // DD(s); + s = s+mSlicer->GetImage()->GetOrigin()[i/2]; // from origin + // DD(s); + s = s-mHiddenImage->GetFirstVTKImageData()->GetOrigin()[i/2]; // from corner second image + s = s/mHiddenImage->GetFirstVTKImageData()->GetSpacing()[i/2]; // in voxel + // DD(s); + + if (s == floor(s)) { + extent2[i] = extent2[i+1] = (int)floor(s); + } + else { + extent2[i] = (int)floor(s); + extent2[i+1] = extent2[i]; + } + // DD(extent2[i]); + } + } + } + else extent2 = extent; + // DD(extent2[0]); + // DD(extent2[1]); + // DD(extent2[2]); + // DD(extent2[3]); + // DD(extent2[4]); + // DD(extent2[5]); + + + mClipper->SetOutputWholeExtent(extent2[0],extent2[1],extent2[2], + extent2[3],extent2[4],extent2[5]); int i; for (i = 0; i < 6;i = i+2) { if (extent[i] == extent[i+1]) { @@ -177,3 +291,151 @@ void vvImageContour::update(double value) { } //------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +void vvImageContour::initializeCacheMode() { + DD("vvImageContour::initializeCacheMode"); + + mPreviousSlice = mPreviousOrientation = 0; + int dim; + if (mHiddenImageIsUsed) dim = mHiddenImage->GetNumberOfDimensions(); + else dim = mSlicer->GetImage()->GetNumberOfDimensions(); + DD(dim); + + mListOfCachedContourActors.resize(dim); + for(int d=0; dGetSize()[d]; + else size = mSlicer->GetImage()->GetSize()[d]; + DD(size); + mListOfCachedContourActors[d].resize(size); + for(int j=0; jGetImageActor()->GetDisplayExtent(); + + // Compute orientation + int orientation; + for (orientation = 0; orientation < 6;orientation = orientation+2) { + if (extent[orientation] == extent[orientation+1]) { + break; + } + } + orientation = orientation/2; + // DD(orientation); + return orientation; +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvImageContour::updateWithFastCacheMode() { + DD("vvImageContour::updateWithFastCacheMode"); + + // Compute orientation + int orientation = computeCurrentOrientation(); + + // Turn off previous actor + DD(mPreviousOrientation); + DD(mPreviousSlice); + if (mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice] != NULL) + mListOfCachedContourActors[mPreviousOrientation][mPreviousSlice]->VisibilityOff(); + mPreviousSlice = mSlice; + mPreviousOrientation = orientation; + + // Display actor if it exist + vtkActor * actor = mListOfCachedContourActors[orientation][mSlice]; + if (actor != NULL) { + DD("Actor exist"); + mListOfCachedContourActors[orientation][mSlice]->VisibilityOn(); + } + else { + vtkImageClip * mClipper; + vtkMarchingSquares * mSquares; + vtkActor * mSquaresActor; + createNewActor(&mSquaresActor, &mSquares, &mClipper); + updateActor(mSquaresActor, mSquares, mClipper, mValue, orientation, mSlice); + mListOfCachedContourActors[orientation][mSlice] = mSquaresActor; + mSquaresActor->VisibilityOn(); + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvImageContour::createNewActor(vtkActor ** actor, + vtkMarchingSquares ** squares, + vtkImageClip ** clipper) { + // DD("vvImageContour::CreateNewActor"); + vtkActor * mSquaresActor = (*actor = vtkActor::New()); + vtkImageClip * mClipper = (*clipper = vtkImageClip::New()); + vtkMarchingSquares * mSquares = (*squares = vtkMarchingSquares::New()); + vtkPolyDataMapper * mSquaresMapper = vtkPolyDataMapper::New(); + + if (mHiddenImageIsUsed) + mClipper->SetInput(mHiddenImage->GetVTKImages()[0]); + else + mClipper->SetInput(mSlicer->GetImage()->GetVTKImages()[0]); + mSquares->SetInput(mClipper->GetOutput()); + mSquaresMapper->SetInput(mSquares->GetOutput()); + mSquaresMapper->ScalarVisibilityOff(); + mSquaresActor->SetMapper(mSquaresMapper); + mSquaresActor->GetProperty()->SetColor(1.0,0,0); + mSquaresActor->SetPickable(0); + mSquaresActor->VisibilityOff(); + mSlicer->GetRenderer()->AddActor(mSquaresActor); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvImageContour::updateActor(vtkActor * actor, + vtkMarchingSquares * squares, + vtkImageClip * clipper, + int threshold, int orientation, int slice) { + // DD("Update Actor according to extend/threshold"); + + int* extent = mSlicer->GetImageActor()->GetDisplayExtent(); + clipper->SetOutputWholeExtent(extent[0],extent[1],extent[2], + extent[3],extent[4],extent[5]); + squares->SetValue(0, threshold); + + switch (orientation) { + case 0: if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice) { + actor->SetPosition(1,0,0); + } + else { + actor->SetPosition(-1,0,0); + } + break; + case 1: if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice) { + actor->SetPosition(0,1,0); + } + else { + actor->SetPosition(0,-1,0); + } + break; + case 2: if (mSlicer->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice) { + actor->SetPosition(0,0,1); + } + else { + actor->SetPosition(0,0,-1); + } + break; + } + squares->Update(); +} +//------------------------------------------------------------------------------ + + diff --git a/vv/vvImageContour.h b/vv/vvImageContour.h index 5b16d35..ad1143d 100644 --- a/vv/vvImageContour.h +++ b/vv/vvImageContour.h @@ -17,11 +17,14 @@ ======================================================================-====*/ #ifndef VVIMAGECONTOUR_H #define VVIMAGECONTOUR_H + #include "clitkCommon.h" #include "vvSlicer.h" + class vtkImageClip; class vtkMarchingSquares; class vtkActor; +class vvImage; //------------------------------------------------------------------------------ class vvImageContour @@ -36,17 +39,42 @@ class vvImageContour void hideActors(); void showActors(); void setColor(double r, double g, double b); + void setImage(vvImage::Pointer image); + void setPreserveModeEnabled(bool b); protected: vvSlicer * mSlicer; int mSlice; int mTSlice; double mValue; + bool mHiddenImageIsUsed; + vvImage::Pointer mHiddenImage; + bool mDisplayModeIsPreserveMemory; + // For preserveMemory mode std::vector mClipperList; std::vector mSquaresList; std::vector mSquaresActorList; + // For fast cache mode + int mPreviousSlice; + int mPreviousOrientation; + std::vector > mListOfCachedContourActors; + + // Functions + void initializeCacheMode(); + void updateWithPreserveMemoryMode(); + void updateWithFastCacheMode(); + void createNewActor(vtkActor ** actor, + vtkMarchingSquares ** squares, + vtkImageClip ** clipper); + void updateActor(vtkActor * actor, + vtkMarchingSquares * squares, + vtkImageClip * clipper, + int threshold, int orientation, int slice); + void createActor(int orientation, int slice); + int computeCurrentOrientation(); + }; // end class vvImageContour //------------------------------------------------------------------------------ diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx index 422f3ef..c7d05c6 100644 --- a/vv/vvMainWindow.cxx +++ b/vv/vvMainWindow.cxx @@ -2378,7 +2378,8 @@ void vvMainWindow::NOVerticalSliderChanged() { if (DataTree->topLevelItem(i)->data(COLUMN_UL_VIEW,Qt::CheckStateRole).toInt() > 1) { mSlicerManagers[i]->GetSlicer(0)->SetSlice(value); - mSlicerManagers[i]->UpdateSlice(0); // <-- DS add this. Not too much update ? + // mSlicerManagers[i]->UpdateSlice(0); + // <-- DS add this. Not too much update ? YES. break; } } diff --git a/vv/vvSlicerManager.cxx b/vv/vvSlicerManager.cxx index 5380192..8535686 100644 --- a/vv/vvSlicerManager.cxx +++ b/vv/vvSlicerManager.cxx @@ -635,6 +635,8 @@ void vvSlicerManager::UpdateViews(int current,int slicer) mSlicers[i]->SetSlice((int)floor(x)); break; } + // DD("UpdateViews::"); + // DD(i); UpdateSlice(i); UpdateTSlice(i); } @@ -932,6 +934,9 @@ void vvSlicerManager::UpdateWindowLevel() //---------------------------------------------------------------------------- void vvSlicerManager::UpdateSlice(int slicer) { + // DD("vvSlicerManager::UpdateSlice emit UpdateSlice"); + // DD(slicer); + // DD(mSlicers[slicer]->GetSlice()); emit UpdateSlice(slicer, mSlicers[slicer]->GetSlice()); } //---------------------------------------------------------------------------- diff --git a/vv/vvToolCropImage.cxx b/vv/vvToolCropImage.cxx index 0b1b540..74c1e4c 100644 --- a/vv/vvToolCropImage.cxx +++ b/vv/vvToolCropImage.cxx @@ -56,7 +56,7 @@ vvToolCropImage::~vvToolCropImage() { //------------------------------------------------------------------------------ bool vvToolCropImage::close() { - for(int i=0; i<6; i++) mReducedExtent[i] = mInitialExtent[i]; + for(int i=0; iGetImage()->GetFirstVTKImageData()->GetWholeExtent(); - for(int i=0; i<6; i++) mInitialExtent[i] = mReducedExtent[i]; + for(int i=0; iNumberOfSlicers(); i++) { //DD(i); //DD(mReducedExtent[i]); diff --git a/vv/vvToolImageArithm.cxx b/vv/vvToolImageArithm.cxx index f7077a8..3ab3965 100644 --- a/vv/vvToolImageArithm.cxx +++ b/vv/vvToolImageArithm.cxx @@ -57,7 +57,7 @@ void vvToolImageArithm::Initialize() { SetToolMenuName("ImageArithm"); SetToolIconFilename(":/common/icons/arithm.png"); SetToolTip("Perform simple arithmetic operations on one or two images."); - SetToolExperimental(true); + SetToolExperimental(false); } //------------------------------------------------------------------------------ -- 2.45.2