ADD_SUBDIRECTORY(${CLITK_SOURCE_DIR}/tests ${PROJECT_BINARY_DIR}/tests)
ENDIF(BUILD_TESTING)
+
ENDIF (${LIBSTATGRAB} MATCHES "LIBSTATGRAB-NOTFOUND")
ENDIF()
#=========================================================
+
+
+#=========================================================
+### Check if ITK was compiled with SYSTEM_GDCM = ON
+SET(CLITK_USE_SYSTEM_GDCM FALSE)
+IF(ITK_VERSION_MAJOR LESS "4")
+ IF(ITK_USE_SYSTEM_GDCM)
+ SET(CLITK_USE_SYSTEM_GDCM TRUE)
+ ENDIF(ITK_USE_SYSTEM_GDCM)
+ELSE(ITK_VERSION_MAJOR LESS "4")
+ SET(GDCM_INCLUDE_INSTALL ".*include/gdcm-.*")
+ SET(GDCM_INCLUDE_BUILD ".*/Source/MediaStorageAndFileFormat")
+ IF(NOT ITKGDCM_INCLUDE_DIRS MATCHES ${GDCM_INCLUDE_BUILD})
+ SET(CLITK_USE_SYSTEM_GDCM TRUE)
+ ENDIF()
+ENDIF(ITK_VERSION_MAJOR LESS "4")
+
+#DD(CLITK_USE_SYSTEM_GDCM)
+
TARGET_LINK_LIBRARIES(clitkCommon statgrab)
ENDIF(CLITK_MEMORY_INFO)
-### Check if ITK was compiled with SYSTEM_GDCM = ON and set the gdcm libraries accordingly
-SET(CLITK_USE_SYSTEM_GDCM FALSE)
-IF(ITK_VERSION_MAJOR LESS "4")
- IF(ITK_USE_SYSTEM_GDCM)
- SET(CLITK_USE_SYSTEM_GDCM TRUE)
- ENDIF(ITK_USE_SYSTEM_GDCM)
-ELSE(ITK_VERSION_MAJOR LESS "4")
- SET(GDCM_INCLUDE_INSTALL ".*include/gdcm-.*")
- SET(GDCM_INCLUDE_BUILD ".*/Source/MediaStorageAndFileFormat")
- IF(ITKGDCM_INCLUDE_DIRS MATCHES ${GDCM_INCLUDE_BUILD} OR ITKGDCM_INCLUDE_DIRS MATCHES ${GDCM_INCLUDE_INSTALL})
- SET(CLITK_USE_SYSTEM_GDCM TRUE)
- ENDIF(ITKGDCM_INCLUDE_DIRS MATCHES ${GDCM_INCLUDE_BUILD} OR ITKGDCM_INCLUDE_DIRS MATCHES ${GDCM_INCLUDE_INSTALL})
-ENDIF(ITK_VERSION_MAJOR LESS "4")
-IF(CLITK_USE_SYSTEM_GDCM)
- SET(CLITK_GDCM_LIBRARIES gdcmDSED)
-ENDIF(CLITK_USE_SYSTEM_GDCM)
+### Set add libraries if system GDCM
+#DD(CLITK_USE_SYSTEM_GDCM)
+IF (CLITK_USE_SYSTEM_GDCM)
+ FIND_PACKAGE(GDCM REQUIRED)
+ #DD(GDCM_USE_FILE)
+ #DD(GDCM_INCLUDE_DIRS)
+ #DD(GDCM_LIBRARY_DIRS)
+ #SET(CLITK_GDCM_LIBRARIES gdcmDSED)
+ SET(CLITK_GDCM_LIBRARIES gdcmDICT gdcmMSFF vtkgdcm)
+ #DD(CLITK_GDCM_LIBRARIES)
+ENDIF()
TARGET_LINK_LIBRARIES(clitkCommon vtkCommon vtkImaging ${ITK_LIBRARIES} ${CLITK_GDCM_LIBRARIES})
clitkDicomRT_ROI.cxx
clitkDicomRT_StructureSet.cxx
clitkDicomRTStruct2ImageFilter.cxx
-)
+ )
-TARGET_LINK_LIBRARIES(clitkDicomRTStruct vtkHybrid ${CLITK_GDCM_LIBRARIES})
+TARGET_LINK_LIBRARIES(clitkDicomRTStruct vtkHybrid ${CLITK_GDCM_LIBRARIES})
#ADD_LIBRARY(clitkCommonShared SHARED ${clitkCommon_SRC})
#SET_TARGET_PROPERTIES(clitkCommonShared PROPERTIES COMPILE_FLAGS -fPIC)
#cmakedefine01 CLITK_EXPERIMENTAL
#cmakedefine01 CLITK_MEMORY_INFO
#cmakedefine01 CLITK_PRIVATE_FEATURES
+#cmakedefine01 CLITK_USE_SYSTEM_GDCM
// Global environment variables
#define OS_NAME "@CMAKE_SYSTEM@"
}
// Get Mesh
- vtkPolyData * mesh = mROI->GetMesh();
+ vtkPolyData * mesh = mROI->GetMesh();
// Get bounds
double *bounds=mesh->GetBounds();
- // for(int i=0; i<6; i++){
-// DD(bounds[i]);
-// }
// Compute origin
std::vector<double> origin;
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));
#include <vtkAppendPolyData.h>
#include <vtkImageClip.h>
#include <vtkMarchingSquares.h>
+#include <vtkPolyDataWriter.h>
#if GDCM_MAJOR_VERSION == 2
#include "gdcmAttribute.h"
mBackgroundValue = 0;
mForegroundValue = 1;
SetDicomUptodateFlag(false);
+ mFilename = "";
}
//--------------------------------------------------------------------
#if GDCM_MAJOR_VERSION == 2
bool clitk::DicomRT_ROI::Read(gdcm::Item * itemInfo, gdcm::Item * itemContour)
{
+ FATAL("Error : compile vv with itk4 + external gdcm");
// Keep dicom item
mItemInfo = itemInfo;
mItemContour = itemContour;
#if GDCM_MAJOR_VERSION == 2
-
//--------------------------------------------------------------------
void clitk::DicomRT_ROI::UpdateDicomItem()
{
+ FATAL("Error : compile vv with itk4 + external gdcm");
+
if (GetDicomUptoDateFlag()) return;
DD("ROI::UpdateDicomItem");
DD(GetName());
//--------------------------------------------------------------------
void clitk::DicomRT_ROI::ComputeContoursFromImage()
{
+ FATAL("ComputeContoursFromImage should not be call. To be replace");
DD("ComputeMeshFromImage");
// Check that an image is loaded
DDV(extent, 6);
// std::vector<int> extend;
- // Prepare the marching squares
- vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
- squares->SetInput(clipper->GetOutput());
// Loop on slice
uint n = image->GetDimensions()[2];
DD(n);
+ DD(mListOfContours.size());
+ mListOfContours.resize(n); /// ???FIXME
+ DD(mListOfContours.size());
+ std::vector<vtkSmartPointer<vtkPolyData> > contours;
for(uint i=0; i<n; i++) {
+ DD(i);
+
+ // FIXME vtkDiscreteMarchingCubes INSTEAD
+
+
+ vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
+ squares->SetInput(image);
+ squares->SetImageRange(extent[0], extent[1], extent[2], extent[3], i, i);
+ squares->SetValue(1, 1.0);
+ squares->Update();
+ DD(squares->GetNumberOfContours());
+
+ //clitk::DicomRT_Contour * contour = new clitk::DicomRT_Contour();
+ //mListOfContours[i]->SetMesh(squares->GetOutput());
+
+
+ vtkSmartPointer<vtkPolyData> m = squares->GetOutput();
+ contours.push_back(m);
+
+ /*
// Clip to the current slice
extent[4] = extent[5] = image->GetOrigin()[2]+i*image->GetSpacing()[2];
DDV(extent, 6);
+ // Prepare the marching squares
+ vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
clipper->SetOutputWholeExtent(extent[0],extent[1],extent[2],
- extent[3],extent[4],extent[5]);
-
+ extent[3],extent[4],extent[5]);
+ squares->SetInput(clipper->GetOutput());
squares->Update();
DD(squares->GetNumberOfContours());
mListOfContours[i]->SetMesh(squares->GetOutput());
+ */
}
+ DD("done");
+
+ vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();
+ for(unsigned int i=0; i<n; i++) {
+ append->AddInput(contours[i]);
+ }
+ append->Update();
+
+ mMesh = vtkSmartPointer<vtkPolyData>::New();
+ mMesh->DeepCopy(append->GetOutput());
+
+ // Write vtk
+ vtkPolyDataWriter * w = vtkPolyDataWriter::New();
+ w->SetInput(mMesh);
+ w->SetFileName("toto.vtk");
+ w->Write();
+
+ DD("done");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+#if CLITK_USE_SYSTEM_GDCM == 1
+void clitk::DicomRT_ROI::Read(vtkSmartPointer<vtkGDCMPolyDataReader> & reader, int roiindex)
+{
+ vtkRTStructSetProperties * p = reader->GetRTStructSetProperties();
+
+ mName = p->GetStructureSetROIName(roiindex);
+ mNumber = p->GetStructureSetROINumber(roiindex);
+
+ //mColor = //FIXME !!
+
+ SetDicomUptodateFlag(true);
+ // Get the contour
+ mMesh = reader->GetOutput(roiindex);
+ DicomRT_Contour::Pointer c = DicomRT_Contour::New();
+ c->SetMesh(mMesh); // FIXME no GetZ, not GetPoints
+ mMeshIsUpToDate = true;
+ mListOfContours.push_back(c);
}
+#endif
//--------------------------------------------------------------------
+
#include "clitkDicomRT_Contour.h"
#include "vvImage.h"
+#include "clitkConfiguration.h"
+#if CLITK_USE_SYSTEM_GDCM == 1
+#include <vtkGDCMPolyDataReader.h>
+#include <vtkRTStructSetProperties.h>
+#endif
+
namespace clitk {
//--------------------------------------------------------------------
void Read(std::map<int, std::string> & rois, gdcm::SQItem * item);
#endif
+#if CLITK_USE_SYSTEM_GDCM == 1
+ void Read(vtkSmartPointer<vtkGDCMPolyDataReader> & reader, int roiindex);
+#endif
+
protected:
std::string mName;
std::string mFilename;
void clitk::DicomRT_StructureSet::Write(const std::string & filename)
{
#if GDCM_MAJOR_VERSION == 2
- DD("DCM RT Writer");
// Assert that the gdcm file is still open (we can write only if it was readed)
if (mFile == NULL) {
}
// Loop and update each ROI
+ int i=0;
for(ROIIteratorType iter = mROIs.begin(); iter != mROIs.end(); iter++) {
iter->second->UpdateDicomItem();
+ i++;
}
// Write [ Structure Set ROI Sequence ] = 0x3006,0x0020
//--------------------------------------------------------------------
void clitk::DicomRT_StructureSet::Read(const std::string & filename)
{
+#if CLITK_USE_SYSTEM_GDCM == 1
+ vtkSmartPointer<vtkGDCMPolyDataReader> reader = vtkGDCMPolyDataReader::New();
+ reader->SetFileName(filename.c_str());
+ reader->Update();
+
+ // Get global information
+ vtkRTStructSetProperties * p = reader->GetRTStructSetProperties();
+ mStudyID = p->GetStudyInstanceUID();
+ mStudyDate = p->GetStructureSetDate();
+ mLabel = p->GetStructureSetLabel();
+ mName = p->GetStructureSetName();
+ mTime = p->GetStructureSetTime();
+
+ int n = p->GetNumberOfStructureSetROIs();
+ for(unsigned int i=0; i<n; i++) {
+ // Get the roi number
+ int roinumber = p->GetStructureSetROINumber(i);
+ // Create the roi
+ DicomRT_ROI::Pointer roi = DicomRT_ROI::New();
+ roi->Read(reader, i);
+ // Insert in the map
+ mROIs[roinumber] = roi;
+ }
+ return;
+#endif // END version with system gdcm (vtkGDCMPolyDataReader)
+
+
// Open DICOM
#if GDCM_MAJOR_VERSION == 2
+ FATAL("Error : compile vv with itk4 + external gdcm");
+
// Read gdcm file
mReader = new gdcm::Reader;
mReader->SetFileName(filename.c_str());
// Temporary store the list of items
std::map<int, gdcm::Item*> mMapOfROIInfo;
std::map<int, gdcm::Item*> mMapOfROIContours;
+
+std::map<int, clitk::DicomRT_ROI::Pointer> mROIs;
+ std::map<int, std::string> mMapOfROIName;
+#if GDCM_MAJOR_VERSION == 2
+ gdcm::Reader * mReader;
+ gdcm::SmartPointer<gdcm::SequenceOfItems> mROIInfoSequenceOfItems;
+ gdcm::SmartPointer<gdcm::SequenceOfItems> mROIContoursSequenceOfItems;
+#endif
+ gdcm::File * mFile;
+
//----------------------------------
// Read all ROI Names and number
// vv
#include "vvImage.h"
+// gdcm
+#include "clitkConfiguration.h"
+#if CLITK_USE_SYSTEM_GDCM == 1
+#include <vtkGDCMPolyDataReader.h>
+#include <vtkRTStructSetProperties.h>
+#endif
+
// gdcm
#if GDCM_MAJOR_VERSION == 2
+// This is not use if CLITK_USE_SYSTEM_GDCM==1
#include "gdcmReader.h"
#include "gdcmWriter.h"
#include "gdcmAttribute.h"
// Set inputs
itkSetMacro(Input, ImagePointer);
itkGetConstMacro(Input, ImagePointer);
+ itkSetMacro(StructureSetFilename, std::string);
+ itkSetMacro(DicomFolder, std::string);
+ itkSetMacro(OutputFilename, std::string);
// Run filter
void Update();
- // Get output
- itkGetConstMacro(DicomRTStruct, DicomRTStructPointer);
-
protected:
ImagePointer m_Input;
- DicomRTStructPointer m_DicomRTStruct;
+ std::string m_StructureSetFilename;
+ std::string m_DicomFolder;
+ std::string m_OutputFilename;
+
};
//--------------------------------------------------------------------
// clitk
#include "clitkImage2DicomRTStructFilter.h"
+#include "clitkBinaryImageToMeshFilter.h"
#include "clitkImageCommon.h"
#include "vvFromITK.h"
#include <vtkMetaImageWriter.h>
#include <vtkImageData.h>
+// FIXME to remove
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyDataMapper2D.h"
+#include "vtkRenderWindowInteractor.h"
+#include "vtkPolyDataReader.h"
+#include "vtkRenderWindow.h"
+#include "vtkRenderer.h"
+#include "vtkCamera.h"
+#include "vtkProperty.h"
+#include "vtkProperty2D.h"
+
// itk
#include <itkImage.h>
#include <itkVTKImageToImageFilter.h>
+// gdcm
+#include <vtkGDCMPolyDataWriter.h>
+
//--------------------------------------------------------------------
template<class PixelType>
clitk::Image2DicomRTStructFilter<PixelType>::Image2DicomRTStructFilter()
{
DD("Image2DicomRTStructFilter::GenerateData");
- // Read DicomRTStruct
- std::string filename = "RS.zzQAnotmt_french01_.dcm";
- clitk::DicomRT_StructureSet::Pointer structset = clitk::DicomRT_StructureSet::New();
- structset->Read(filename);
+ // Read rt struct
+ vtkSmartPointer<vtkGDCMPolyDataReader> reader = vtkGDCMPolyDataReader::New();
+ reader->SetFileName(m_StructureSetFilename.c_str());
+ reader->Update();
+ DD("reader done");
+
+ // Get properties
+ vtkRTStructSetProperties * p = reader->GetRTStructSetProperties();
+ DD(p->GetNumberOfStructureSetROIs());
+ DD(p->GetStructureSetROIName(0));
+ DD(p->GetStructureSetROINumber(0));
+
+ // Init writer
+ vtkGDCMPolyDataWriter * writer = vtkGDCMPolyDataWriter::New();
+ int numMasks = reader->GetNumberOfOutputPorts() + 1;//add one more
+ DD(numMasks);
+
+ // numMasks = 3; //FIXME temporary
+
+ writer->SetNumberOfInputPorts(numMasks);
+ writer->SetFileName(m_OutputFilename.c_str());
+ writer->SetMedicalImageProperties(reader->GetMedicalImageProperties());
+
+ // List of already present rois
+ vtkStringArray* roiNames = vtkStringArray::New();
+ vtkStringArray* roiAlgorithms = vtkStringArray::New();
+ vtkStringArray* roiTypes = vtkStringArray::New();
+ roiNames->SetNumberOfValues(numMasks);
+ roiAlgorithms->SetNumberOfValues(numMasks);
+ roiTypes->SetNumberOfValues(numMasks);
- DD(structset->GetName());
- clitk::DicomRT_ROI * roi = structset->GetROIFromROINumber(1); // Aorta
+ typedef clitk::BinaryImageToMeshFilter<ImageType> BinaryImageToMeshFilterType;
+ typename BinaryImageToMeshFilterType::Pointer convert = BinaryImageToMeshFilterType::New();
+ convert->SetInput(m_Input);
+ DD("Update");
+ convert->Update();
+ DD("here");
+ DD("end update");
+ vtkPolyData* mesh = convert->GetOutputMesh();
+ DD(mesh->GetNumberOfVerts());
+ DD(mesh->GetNumberOfLines());
+ DD(mesh->GetNumberOfPolys());
+ DD(mesh->GetNumberOfStrips());
+
+ // Add on (FIXME) to replace with binary image
+ // vtkPolyData* blank = vtkPolyData::New();
+ // writer->SetInput(0, blank);
+ writer->SetInput(0, mesh);
+ roiNames->InsertValue(0, "blank");
+ roiAlgorithms->InsertValue(0, "blank");
+ roiTypes->InsertValue(0, "ORGAN");
+
+ for (unsigned int i = 1; i < numMasks; ++i) {
+ // DD(i);
+ writer->SetInput(i, reader->GetOutput(i-1));
+ std::string theString = reader->GetRTStructSetProperties()->GetStructureSetROIName(i-1);
+ roiNames->InsertValue(i, theString);
+ theString = reader->GetRTStructSetProperties()->GetStructureSetROIGenerationAlgorithm(i-1);
+ roiAlgorithms->InsertValue(i, theString);
+ theString = reader->GetRTStructSetProperties()->GetStructureSetRTROIInterpretedType(i-1);
+ roiTypes->InsertValue(i, theString);
+ }
+
+
+ /*
+ // Visu
+ vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New();
+ cubeMapper->SetInput( mesh );
+ cubeMapper->SetScalarRange(0,7);
+ vtkActor *cubeActor = vtkActor::New();
+ cubeActor->SetMapper(cubeMapper);
+ vtkProperty * property = cubeActor->GetProperty();
+ property->SetRepresentationToWireframe();
+
+ vtkRenderer *renderer = vtkRenderer::New();
+ vtkRenderWindow *renWin = vtkRenderWindow::New();
+ renWin->AddRenderer(renderer);
+
+ vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
+ iren->SetRenderWindow(renWin);
+
+ renderer->AddActor(cubeActor);
+ renderer->ResetCamera();
+ renderer->SetBackground(1,1,1);
+
+ renWin->SetSize(300,300);
+
+ renWin->Render();
+ iren->Start();
+ */
+
+
+ // End visu
+
+
+ vtkRTStructSetProperties* theProperties = vtkRTStructSetProperties::New();
+ DD(p->GetStudyInstanceUID());
+ writer->SetRTStructSetProperties(theProperties);
+ /*writer->InitializeRTStructSet2(p,"./",
+ reader->GetRTStructSetProperties()->GetStructureSetLabel(),
+ reader->GetRTStructSetProperties()->GetStructureSetName(),
+ roiNames, roiAlgorithms, roiTypes);*/
+ writer->InitializeRTStructSet(m_DicomFolder,
+ reader->GetRTStructSetProperties()->GetStructureSetLabel(),
+ reader->GetRTStructSetProperties()->GetStructureSetName(),
+ roiNames, roiAlgorithms, roiTypes);
+
+ DD("after init");
+ writer->Write();
+ DD("write done");
+
+ reader->Delete();
+ roiNames->Delete();
+ roiTypes->Delete();
+ //theProperties->Delete();
+ roiAlgorithms->Delete();
+ //blank->Delete();
+ writer->Delete();
+
+ ////////////////////
+
+
+ /*
+
+ // DicomRTStruct
+ DD(m_StructureSet->GetName());
+ clitk::DicomRT_ROI * roi = m_StructureSet->GetROIFromROINumber(1); // Aorta
DD(roi->GetName());
DD(roi->GetROINumber());
+
+ // Get
+
+
+
+
// Add an image to the roi
vvImage::Pointer im = vvImageFromITK<3, PixelType>(m_Input);
roi->SetImage(im);
// Get one contour
DD("Compute Mesh");
- roi->ComputeMeshFromImage();
+ roi->ComputeContoursFromImage(); // FIXME do the set mesh for the moment (to change)
+ // roi->ComputeMeshFromContour();
vtkSmartPointer<vtkPolyData> mesh = roi->GetMesh();
DD("done");
// points->SetPoint(i, p);
// }
roi->SetName("TOTO");
- roi->SetDicomUptodateFlag(false); // indicate that dicom info must be updated from the mesh.
+ roi->SetDicomUptodateFlag(true); // indicate that dicom info must be updated from the mesh.
// Convert to dicom ?
DD("TODO");
// Write
structset->Write("toto.dcm");
+ */
}
//--------------------------------------------------------------------
+++ /dev/null
-/*=========================================================================
- Program: vv http://www.creatis.insa-lyon.fr/rio/vv
-
- Authors belong to:
- - University of LYON http://www.universite-lyon.fr/
- - Léon Bérard cancer center http://www.centreleonberard.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 See included LICENSE.txt file
- - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================*/
-/*=========================================================================
-
- Program: GDCM (Grassroots DICOM). A DICOM library
-
- Copyright (c) 2006-2011 Mathieu Malaterre
- All rights reserved.
- See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-#include "vtkGDCMPolyDataReader.h"
-
-#include "vtkObjectFactory.h"
-#include "vtkInformation.h"
-#include "vtkInformationVector.h"
-#include "vtkPolyData.h"
-#include "vtkStreamingDemandDrivenPipeline.h"
-#include "vtkDoubleArray.h"
-#include "vtkCellArray.h"
-#include "vtkCellData.h"
-#include "vtkMedicalImageProperties.h"
-#include "vtkRTStructSetProperties.h"
-
-#include "gdcmReader.h"
-#include "gdcmSmartPointer.h"
-#include "gdcmAttribute.h"
-#include "gdcmSequenceOfItems.h"
-
-vtkCxxRevisionMacro(vtkGDCMPolyDataReader, "$Revision: 1.1 $")
-vtkStandardNewMacro(vtkGDCMPolyDataReader)
-
-//----------------------------------------------------------------------------
-vtkGDCMPolyDataReader::vtkGDCMPolyDataReader()
-{
- this->FileName = NULL;
- this->SetNumberOfInputPorts(0);
- this->MedicalImageProperties = vtkMedicalImageProperties::New();
- this->RTStructSetProperties = vtkRTStructSetProperties::New();
-}
-
-//----------------------------------------------------------------------------
-vtkGDCMPolyDataReader::~vtkGDCMPolyDataReader()
-{
- this->SetFileName(0);
- this->MedicalImageProperties->Delete();
- this->RTStructSetProperties->Delete();
-}
-
-//----------------------------------------------------------------------------
-// inline keyword is needed since GetStringValueFromTag was copy/paste from vtkGDCMImageReader
-// FIXME: need to restructure code to avoid copy/paste
-inline const char *GetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
-{
- static std::string buffer;
- buffer = ""; // cleanup previous call
-
- if( ds.FindDataElement( t ) )
- {
- const gdcm::DataElement& de = ds.GetDataElement( t );
- const gdcm::ByteValue *bv = de.GetByteValue();
- if( bv ) // Can be Type 2
- {
- buffer = std::string( bv->GetPointer(), bv->GetLength() );
- // Will be padded with at least one \0
- }
- }
-
- // Since return is a const char* the very first \0 will be considered
- return buffer.c_str();
-}
-
-//----------------------------------------------------------------------------
-void vtkGDCMPolyDataReader::FillMedicalImageInformation(const gdcm::Reader &reader)
-{
- const gdcm::File &file = reader.GetFile();
- const gdcm::DataSet &ds = file.GetDataSet();
-
- this->RTStructSetProperties->SetStructureSetLabel( GetStringValueFromTag( gdcm::Tag(0x3006,0x0002), ds) );
- this->RTStructSetProperties->SetStructureSetName( GetStringValueFromTag( gdcm::Tag(0x3006,0x0004), ds) );
- this->RTStructSetProperties->SetStructureSetDate( GetStringValueFromTag( gdcm::Tag(0x3006,0x0008), ds) );
- this->RTStructSetProperties->SetStructureSetTime( GetStringValueFromTag( gdcm::Tag(0x3006,0x0009), ds) );
- this->RTStructSetProperties->SetSOPInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0008,0x0018), ds) );
- this->RTStructSetProperties->SetStudyInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000d), ds) );
- this->RTStructSetProperties->SetSeriesInstanceUID( GetStringValueFromTag( gdcm::Tag(0x0020,0x000e), ds) );
-
- // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h
- // For ex: DICOM (0010,0010) = DOE,JOHN
- this->MedicalImageProperties->SetPatientName( GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds) );
- // For ex: DICOM (0010,0020) = 1933197
- this->MedicalImageProperties->SetPatientID( GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds) );
- // For ex: DICOM (0010,1010) = 031Y
- this->MedicalImageProperties->SetPatientAge( GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds) );
- // For ex: DICOM (0010,0040) = M
- this->MedicalImageProperties->SetPatientSex( GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
- // For ex: DICOM (0010,0030) = 19680427
- this->MedicalImageProperties->SetPatientBirthDate( GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
-#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
- // For ex: DICOM (0008,0020) = 20030617
- this->MedicalImageProperties->SetStudyDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds) );
-#endif
- // For ex: DICOM (0008,0022) = 20030617
- this->MedicalImageProperties->SetAcquisitionDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds) );
-#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
- // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012
- this->MedicalImageProperties->SetStudyTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds) );
-#endif
- // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012
- this->MedicalImageProperties->SetAcquisitionTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds) );
- // For ex: DICOM (0008,0023) = 20030617
- this->MedicalImageProperties->SetImageDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds) );
- // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012
- this->MedicalImageProperties->SetImageTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds) );
- // For ex: DICOM (0020,0013) = 1
- this->MedicalImageProperties->SetImageNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds) );
- // For ex: DICOM (0020,0011) = 902
- this->MedicalImageProperties->SetSeriesNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
- // For ex: DICOM (0008,103e) = SCOUT
- this->MedicalImageProperties->SetSeriesDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
- // For ex: DICOM (0020,0010) = 37481
- this->MedicalImageProperties->SetStudyID( GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
- // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
- this->MedicalImageProperties->SetStudyDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
- // For ex: DICOM (0008,0060)= CT
- this->MedicalImageProperties->SetModality( GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
- // For ex: DICOM (0008,0070) = Siemens
- this->MedicalImageProperties->SetManufacturer( GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds) );
- // For ex: DICOM (0008,1090) = LightSpeed QX/i
- this->MedicalImageProperties->SetManufacturerModelName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds) );
- // For ex: DICOM (0008,1010) = LSPD_OC8
- this->MedicalImageProperties->SetStationName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds) );
- // For ex: DICOM (0008,0080) = FooCity Medical Center
- this->MedicalImageProperties->SetInstitutionName( GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds) );
- // For ex: DICOM (0018,1210) = Bone
- this->MedicalImageProperties->SetConvolutionKernel( GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds) );
- // For ex: DICOM (0018,0050) = 0.273438
- this->MedicalImageProperties->SetSliceThickness( GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds) );
- // For ex: DICOM (0018,0060) = 120
- this->MedicalImageProperties->SetKVP( GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds) );
- // For ex: DICOM (0018,1120) = 15
- this->MedicalImageProperties->SetGantryTilt( GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds) );
- // For ex: DICOM (0018,0081) = 105
- this->MedicalImageProperties->SetEchoTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds) );
- // For ex: DICOM (0018,0091) = 35
- this->MedicalImageProperties->SetEchoTrainLength( GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds) );
- // For ex: DICOM (0018,0080) = 2040
- this->MedicalImageProperties->SetRepetitionTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds) );
- // For ex: DICOM (0018,1150) = 5
- this->MedicalImageProperties->SetExposureTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds) );
- // For ex: DICOM (0018,1151) = 400
- this->MedicalImageProperties->SetXRayTubeCurrent( GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds) );
- // For ex: DICOM (0018,1152) = 114
- this->MedicalImageProperties->SetExposure( GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds) );
-
- // virtual void AddWindowLevelPreset(double w, double l);
- // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter
- // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth
- gdcm::Tag twindowcenter(0x0028,0x1050);
- gdcm::Tag twindowwidth(0x0028,0x1051);
- if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) )
- {
- const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter );
- const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth );
- const gdcm::ByteValue *bvwc = windowcenter.GetByteValue();
- const gdcm::ByteValue *bvww = windowwidth.GetByteValue();
- if( bvwc && bvww ) // Can be Type 2
- {
- //gdcm::Attributes<0x0028,0x1050> at;
- gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elwc;
- std::stringstream ss1;
- std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() );
- ss1.str( swc );
- gdcm::VR vr = gdcm::VR::DS;
- unsigned int vrsize = vr.GetSizeof();
- unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), swc.size());
- elwc.SetLength( count * vrsize );
- elwc.Read( ss1 );
- std::stringstream ss2;
- std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() );
- ss2.str( sww );
- gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elww;
- elww.SetLength( count * vrsize );
- elww.Read( ss2 );
- //assert( elww.GetLength() == elwc.GetLength() );
- for(unsigned int i = 0; i < elwc.GetLength(); ++i)
- {
- this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) );
- }
- }
- }
- gdcm::Tag twindowexplanation(0x0028,0x1055);
- if( ds.FindDataElement( twindowexplanation ) )
- {
- const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation );
- const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue();
- if( bvwe ) // Can be Type 2
- {
- int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets();
- gdcm::Element<gdcm::VR::LO,gdcm::VM::VM1_n> elwe; // window explanation
- gdcm::VR vr = gdcm::VR::LO;
- std::stringstream ss;
- ss.str( "" );
- std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() );
- unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), swe.size()); (void)count;
- // I found a case with only one W/L but two comments: WINDOW1\WINDOW2
- // SIEMENS-IncompletePixelData.dcm
- //assert( count >= (unsigned int)n );
- elwe.SetLength( /*count*/ n * vr.GetSizeof() );
- ss.str( swe );
- elwe.Read( ss );
- for(int i = 0; i < n; ++i)
- {
- this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() );
- }
- }
- }
-
-#if 0
- // gdcmData/JDDICOM_Sample4.dcm
- // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality
- gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage;
- ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality );
- gdcm::MediaStorage ms2;
- ms2.SetFromFile( reader.GetFile() );
- if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage )
- {
- vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality()
- << " Will be set instead to the known one: " << ms2.GetModality() )
- this->MedicalImageProperties->SetModality( ms2.GetModality() );
- }
-#endif
-
- // Add more info:
-
-}
-
-//(3006,0022) ?? (IS) [2 ] # 2,1 ROI Number
-//(3006,0024) ?? (UI) [2.16.840.1.114362.1.759508.1251415878280.193] # 44,1 Referenced Frame of Reference UID
-//(3006,0026) ?? (LO) [Bladder ] # 8,1 ROI Name
-//(3006,0036) ?? (CS) [MANUAL] # 6,1 ROI Generation Algorithm
-
-int vtkGDCMPolyDataReader::RequestData_RTStructureSetStorage(gdcm::Reader const &reader,
- vtkInformationVector *outputVector)
-{
-// This is done in RequestInformation
-// gdcm::MediaStorage ms;
-// ms.SetFromFile( reader.GetFile() );
-// //std::cout << ms << std::endl;
-// if( ms != gdcm::MediaStorage::RTStructureSetStorage )
-// {
-// return 0;
-// }
-
- const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
- // (3006,0010) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedFrameOfReferenceSequence
- // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
- // (3006,0039) SQ (Sequence with explicit length #=4) # 24216, 1 ROIContourSequence
- gdcm::Tag troicsq(0x3006,0x0039);
- if( !ds.FindDataElement( troicsq ) )
- {
- return 0;
- }
- gdcm::Tag tssroisq(0x3006,0x0020);
- if( !ds.FindDataElement( tssroisq ) )
- {
- return 0;
- }
- gdcm::Tag trefframerefsq(0x3006,0x0010);
- if( !ds.FindDataElement( trefframerefsq ) )
- {
- return 0;
- }
- const gdcm::DataElement &refframerefsq = ds.GetDataElement( trefframerefsq );
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0 = refframerefsq.GetValueAsSQ();
- if( !sqi0 || !sqi0->GetNumberOfItems() )
- {
- return 0;
- }
- assert( sqi0->GetNumberOfItems() == 1 );
- for(unsigned int pd = 0; pd < sqi0->GetNumberOfItems(); ++pd)
- {
- const gdcm::Item & item = sqi0->GetItem(pd+1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
- // (3006,0012) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedStudySequence
- gdcm::Attribute<0x0020,0x052> frameofreferenceuid;
- frameofreferenceuid.SetFromDataSet( nestedds );
- this->RTStructSetProperties->SetReferenceFrameOfReferenceUID(
- frameofreferenceuid.GetValue() );
- gdcm::Tag trtrefstudysq(0x3006,0x0012);
- if( !nestedds.FindDataElement( trtrefstudysq) )
- {
- return 0;
- }
- const gdcm::DataElement &rtrefstudysq = nestedds.GetDataElement( trtrefstudysq );
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi00 = rtrefstudysq.GetValueAsSQ();
- if( !sqi00 || !sqi00->GetNumberOfItems() )
- {
- return 0;
- }
- assert( sqi00->GetNumberOfItems() == 1 );
- for(unsigned int pd0 = 0; pd0 < sqi00->GetNumberOfItems(); ++pd0)
- {
- const gdcm::Item & item = sqi00->GetItem(pd0+1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
-
- // (3006,0014) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedSeriesSequence
- gdcm::Tag trtrefseriessq(0x3006,0x0014);
- if( !nestedds.FindDataElement( trtrefseriessq) )
- {
- return 0;
- }
- const gdcm::DataElement &rtrefseriessq = nestedds.GetDataElement( trtrefseriessq);
-
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi000 = rtrefseriessq.GetValueAsSQ();
- if( !sqi000 || !sqi000->GetNumberOfItems() )
- {
- return 0;
- }
- assert( sqi000->GetNumberOfItems() == 1 );
- for(unsigned int pd00 = 0; pd00 < sqi000->GetNumberOfItems(); ++pd00)
- {
- const gdcm::Item & item = sqi000->GetItem(pd00+1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
-
- gdcm::Attribute<0x0020,0x000e> seriesinstanceuid;
- seriesinstanceuid.SetFromDataSet( nestedds );
- this->RTStructSetProperties->SetReferenceSeriesInstanceUID(
- seriesinstanceuid.GetValue() );
-
-
- // (3006,0016) SQ (Sequence with undefined length #=162) # u/l, 1 ContourImageSequence
- gdcm::Tag tcontourimageseq(0x3006,0x0016);
- if( !nestedds.FindDataElement( tcontourimageseq) )
- {
- return 0;
- }
- const gdcm::DataElement &contourimageseq = nestedds.GetDataElement( tcontourimageseq );
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi0000 = contourimageseq.GetValueAsSQ();
- if( !sqi0000 || !sqi0000->GetNumberOfItems() )
- {
- return 0;
- }
-
- assert( sqi0000->GetNumberOfItems() != 1 );
- for(unsigned int pd000 = 0; pd000 < sqi0000->GetNumberOfItems(); ++pd000)
- {
- const gdcm::Item & item = sqi0000->GetItem(pd000+1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
- gdcm::Attribute<0x0008,0x1150> refsopclassuid;
- refsopclassuid.SetFromDataSet( nestedds );
- gdcm::Attribute<0x0008,0x1155> refinstanceuid;
- refinstanceuid.SetFromDataSet( nestedds );
- this->RTStructSetProperties->AddReferencedFrameOfReference( refsopclassuid.GetValue().c_str(),
-refinstanceuid.GetValue().c_str() );
- }
-
- }
-
- }
- }
-
- const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq );
- //std::cout << roicsq << std::endl;
- //const gdcm::SequenceOfItems *sqi_debug = roicsq.GetSequenceOfItems();
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = roicsq.GetValueAsSQ();
- if( !sqi || !sqi->GetNumberOfItems() )
- {
- return 0;
- }
- const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
- //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems();
- gdcm::SmartPointer<gdcm::SequenceOfItems> ssqi = ssroisq.GetValueAsSQ();
- if( !ssqi || !ssqi->GetNumberOfItems() )
- {
- return 0;
- }
-
- // For each Item in the DataSet create a vtkPolyData
- for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd)
- {
- //StructureSetROI structuresetroi;
- // get the info object
- vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
-
- // get the ouptut
- vtkPolyData *output = vtkPolyData::SafeDownCast(
- outInfo1->Get(vtkDataObject::DATA_OBJECT()));
-
-
- const gdcm::Item & item = sqi->GetItem(pd+1); // Item start at #1
- //std::cout << item << std::endl;
- const gdcm::Item & sitem = ssqi->GetItem(pd+1); // Item start at #1
- const gdcm::DataSet& snestedds = sitem.GetNestedDataSet();
- // (3006,0026) ?? (LO) [date] # 4,1 ROI Name
- gdcm::Tag stcsq(0x3006,0x0026);
- if( !snestedds.FindDataElement( stcsq ) )
- {
- continue;
- }
- const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq );
- std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
- //structuresetroi.ROIName = s;
- gdcm::Attribute<0x3006,0x0022> roinumber;
- roinumber.SetFromDataSet( snestedds );
- //structuresetroi.ROINumber = roinumber.GetValue();
- gdcm::Attribute<0x3006,0x0024> refframeuid;
- refframeuid.SetFromDataSet( snestedds );
- //structuresetroi.RefFrameRefUID = refframeuid.GetValue();
- gdcm::Attribute<0x3006,0x0026> roiname;
- roiname.SetFromDataSet( snestedds );
- assert( s == roiname.GetValue() );
- gdcm::Attribute<0x3006,0x0036> roigenalg;
- roigenalg.SetFromDataSet( snestedds );
- //structuresetroi.ROIGenerationAlgorithm = roigenalg.GetValue();
- //structuresetrois.push_back( structuresetroi );
-
- this->RTStructSetProperties->AddStructureSetROI(
- roinumber.GetValue(),
- refframeuid.GetValue(),
- roiname.GetValue(),
- roigenalg.GetValue()
- );
-
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
- //std::cout << nestedds << std::endl;
- //(3006,002a) IS [255\192\96] # 10,3 ROI Display Color
- gdcm::Tag troidc(0x3006,0x002a);
- gdcm::Attribute<0x3006,0x002a> color = {};
- if( nestedds.FindDataElement( troidc) )
- {
- const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc );
- color.SetFromDataElement( decolor );
- //std::cout << "color:" << color[0] << "," << color[1] << "," << color[2] << std::endl;
- }
- //(3006,0040) SQ (Sequence with explicit length #=8) # 4326, 1 ContourSequence
- gdcm::Tag tcsq(0x3006,0x0040);
- if( !nestedds.FindDataElement( tcsq ) )
- {
- continue;
- }
- const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq );
- //std::cout << csq << std::endl;
-
- //const gdcm::SequenceOfItems *sqi2 = csq.GetSequenceOfItems();
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi2 = csq.GetValueAsSQ();
- if( !sqi2 || !sqi2->GetNumberOfItems() )
- {
- continue;
- }
- unsigned int nitems = sqi2->GetNumberOfItems();
- //std::cout << nitems << std::endl;
- //this->SetNumberOfOutputPorts(nitems);
- vtkDoubleArray *scalars = vtkDoubleArray::New();
- scalars->SetNumberOfComponents(3);
-
- vtkPoints *newPts = vtkPoints::New();
- //std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength());
- //std::cout << s << std::endl;
- //newPts->GetData()->SetName( s.c_str() );
- // In VTK there is no API to specify the name of a vtkPolyData, you can only specify Name
- // for the scalars (pointdata or celldata), so let's do that...
- //scalars->SetName( structuresetroi.ROIName.c_str() );
- scalars->SetName( roiname.GetValue().c_str() );
- vtkCellArray *polys = vtkCellArray::New();
- for(unsigned int i = 0; i < nitems; ++i)
- {
- const gdcm::Item & item2 = sqi2->GetItem(i+1); // Item start at #1
-
- const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet();
- //std::cout << nestedds2 << std::endl;
- // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData
- gdcm::Tag tcontourdata(0x3006,0x0050);
- const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata );
- //std::cout << contourdata << std::endl;
-
- //const gdcm::ByteValue *bv = contourdata.GetByteValue();
- gdcm::Attribute<0x3006,0x0042> contgeotype;
- contgeotype.SetFromDataSet( nestedds2 );
- assert( contgeotype.GetValue() == "CLOSED_PLANAR " );
-
- gdcm::Attribute<0x3006,0x0046> numcontpoints;
- numcontpoints.SetFromDataSet( nestedds2 );
-
- gdcm::Attribute<0x3006,0x0050> at;
- at.SetFromDataElement( contourdata );
-
- {
- assert( nestedds2.FindDataElement( gdcm::Tag(0x3006,0x0016) ) );
- const gdcm::DataElement &contourimagesequence = nestedds2.GetDataElement( gdcm::Tag(0x3006,0x0016) );
- gdcm::SmartPointer<gdcm::SequenceOfItems> contourimagesequence_sqi = contourimagesequence.GetValueAsSQ();
- assert( contourimagesequence_sqi && contourimagesequence_sqi->GetNumberOfItems() == 1 );
- const gdcm::Item & theitem = contourimagesequence_sqi->GetItem(1);
- const gdcm::DataSet& nestedds = theitem.GetNestedDataSet();
-
- gdcm::Attribute<0x0008,0x1150> classat;
- classat.SetFromDataSet( nestedds );
- gdcm::Attribute<0x0008,0x1155> instat;
- instat.SetFromDataSet( nestedds );
-
- this->RTStructSetProperties->AddContourReferencedFrameOfReference( pd,
- classat.GetValue(), instat.GetValue() );
- }
-
- //newPts->SetNumberOfPoints( at.GetNumberOfValues() / 3 );
- //assert( at.GetNumberOfValues() % 3 == 0); // FIXME
- const double* pts = at.GetValues();
- vtkIdType buffer[256];
- vtkIdType *ptIds;
- unsigned int npts = at.GetNumberOfValues() / 3;
- assert( npts == numcontpoints.GetValue() );
- if(npts>256)
- {
- ptIds = new vtkIdType[npts];
- }
- else
- {
- ptIds = buffer;
- }
- for(unsigned int i = 0; i < npts * 3; i+=3)
- {
- float x[3];
- x[0] = pts[i+0];
- x[1] = pts[i+1];
- x[2] = pts[i+2];
- vtkIdType ptId = newPts->InsertNextPoint( x );
- ptIds[i / 3] = ptId;
- }
- // Each Contour Data is in fact a Cell:
- vtkIdType cellId = polys->InsertNextCell( npts , ptIds);
- scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0);
- if(npts>256)
- {
- delete[] ptIds;
- }
- }
- output->SetPoints(newPts);
- newPts->Delete();
- output->SetPolys(polys);
- polys->Delete();
- output->GetCellData()->SetScalars(scalars);
- scalars->Delete();
- }
-
- // Add the Observations:
- // we can only be doing it here once all RT are loaded, since we will
- // attach observation to *existing* rtstruct
- gdcm::Tag trtroiobssq(0x3006,0x0080);
- if( !ds.FindDataElement( trtroiobssq ) )
- {
- return 0;
- }
- const gdcm::DataElement &rtroiobssq = ds.GetDataElement( trtroiobssq );
- gdcm::SmartPointer<gdcm::SequenceOfItems> rtroiobssqsqi = rtroiobssq.GetValueAsSQ();
- if( !rtroiobssqsqi || !rtroiobssqsqi->GetNumberOfItems() )
- {
- return 0;
- }
- for(unsigned int obs = 0; obs < rtroiobssqsqi->GetNumberOfItems(); ++obs)
- {
- const gdcm::Item & item = rtroiobssqsqi->GetItem(obs+1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
- gdcm::Attribute<0x3006,0x0082> observationnumber;
- observationnumber.SetFromDataSet( nestedds );
- gdcm::Attribute<0x3006,0x0084> referencedroinumber;
- referencedroinumber.SetFromDataSet( nestedds );
- gdcm::Attribute<0x3006,0x00a4> rtroiinterpretedtype;
- rtroiinterpretedtype.SetFromDataSet( nestedds );
- gdcm::Attribute<0x3006,0x00a6> roiinterpreter;
- roiinterpreter.SetFromDataSet( nestedds );
- this->RTStructSetProperties->
- AddStructureSetROIObservation( referencedroinumber.GetValue(),
- observationnumber.GetValue(),
- rtroiinterpretedtype.GetValue(),
- roiinterpreter.GetValue() );
- }
-
- return 1;
-}
-
-int vtkGDCMPolyDataReader::RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader,
- vtkInformationVector *outputVector)
-{
- const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
- // (5400,0100) SQ (Sequence with undefined length #=1) # u/l, 1 WaveformSequence
- gdcm::Tag twsq(0x5400,0x0100);
- if( !ds.FindDataElement( twsq) )
- {
- return 0;
- }
- const gdcm::DataElement &wsq = ds.GetDataElement( twsq );
- //std::cout << wsq << std::endl;
- //const gdcm::SequenceOfItems *sqi = wsq.GetSequenceOfItems();
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = wsq.GetValueAsSQ();
- if( !sqi || !sqi->GetNumberOfItems() )
- {
- return 0;
- }
-
- const gdcm::Item & item = sqi->GetItem(1); // Item start at #1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
-
- // (5400,1004) US 16 # 2, 1 WaveformBitsAllocated
- gdcm::Tag twba(0x5400,0x1004);
- if( !nestedds.FindDataElement( twba ) )
- {
- return 0;
- }
- const gdcm::DataElement &wba= nestedds.GetDataElement( twba );
-
- //std::cout << wba << std::endl;
- // (5400,1006) CS [SS] # 2, 1 WaveformSampleInterpretation
- // (5400,1010) OW 00ba\0030\ff76\ff8b\00a2\ffd3\ffae\ff50\0062\00c4\011e\00c2\00ba... # 57600, 1 WaveformData
- gdcm::Tag twd(0x5400,0x1010);
- if( !nestedds.FindDataElement( twd ) )
- {
- return 0;
- }
- const gdcm::DataElement &wd = nestedds.GetDataElement( twd );
- const gdcm::ByteValue *bv = wd.GetByteValue();
- size_t len = bv->GetLength();
- int16_t *p = (int16_t*)bv;
-
- // get the info object
- int pd = 0;
- vtkInformation *outInfo1 = outputVector->GetInformationObject(pd);
-
- // get the ouptut
- vtkPolyData *output = vtkPolyData::SafeDownCast(
- outInfo1->Get(vtkDataObject::DATA_OBJECT()));
-
- vtkPoints *newPts = vtkPoints::New();
- size_t npts = len / 2;
- //npts = 10; // DEBUG !
- for(size_t i = 0; i < npts; ++i )
- {
- float x[3];
- x[0] = (float)p[i] / 8800;
- //std::cout << p[i] << std::endl;
- x[1] = i;
- x[2] = 0;
- vtkIdType ptId = newPts->InsertNextPoint( x );
- }
- output->SetPoints(newPts);
- newPts->Delete();
-
- vtkCellArray* lines = vtkCellArray::New();
- for ( int i = 0; i < newPts->GetNumberOfPoints() - 1; ++i )
- {
- vtkIdType topol[2];
- topol[0] = i;
- topol[1] = i+1;
- lines->InsertNextCell( 2, topol );
- }
-
- output->SetLines(lines);
- lines->Delete();
- output->BuildCells();
- //output->GetCellData()->SetScalars(scalars);
- //scalars->Delete();
-
- return 1;
-}
-
-//----------------------------------------------------------------------------
-int vtkGDCMPolyDataReader::RequestData(
- vtkInformation *vtkNotUsed(request),
- vtkInformationVector **vtkNotUsed(inputVector),
- vtkInformationVector *outputVector)
-{
- vtkInformation *outInfo = outputVector->GetInformationObject(0);
- //vtkPoints *newPts, *mergedPts;
- //vtkCellArray *newPolys, *mergedPolys;
- //vtkFloatArray *newScalars=0, *mergedScalars=0;
-
- // All of the data in the first piece.
- if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
- {
- return 0;
- }
-
- if ( !this->FileName || !*this->FileName )
- {
- vtkErrorMacro(<<"A FileName must be specified.");
- return 0;
- }
-
- gdcm::Reader reader;
- reader.SetFileName( this->FileName );
- if( !reader.Read() )
- {
- return 0;
- }
-
- gdcm::MediaStorage ms;
- ms.SetFromFile( reader.GetFile() );
-
- int ret;
- if( ms == gdcm::MediaStorage::RTStructureSetStorage )
- {
- ret = this->RequestData_RTStructureSetStorage(reader, outputVector);
- }
- else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
- {
- ret = this->RequestData_HemodynamicWaveformStorage(reader, outputVector);
- }
- else
- {
- // not handled assume error
- ret = 0;
- }
-
- return ret;
-}
-
-int vtkGDCMPolyDataReader::RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader)
-{
- const gdcm::DataSet& ds = reader.GetFile().GetDataSet();
- // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence
- gdcm::Tag tssroisq(0x3006,0x0020);
- if( !ds.FindDataElement( tssroisq ) )
- {
- return 0;
- }
-
- const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
- //const gdcm::SequenceOfItems *sqi = ssroisq.GetSequenceOfItems();
- gdcm::SmartPointer<gdcm::SequenceOfItems> sqi = ssroisq.GetValueAsSQ();
- if( !sqi || !sqi->GetNumberOfItems() )
- {
- return 0;
- }
- unsigned int npds = sqi->GetNumberOfItems();
-
- //std::cout << "Nb pd:" << npds << std::endl;
- this->SetNumberOfOutputPorts( npds );
-
- // Allocate
- for(unsigned int i = 1; i < npds; ++i) // first output is allocated for us
- {
- vtkPolyData *output2 = vtkPolyData::New();
- this->GetExecutive()->SetOutputData(i, output2);
- output2->Delete();
- }
- return 1;
-}
-
-int vtkGDCMPolyDataReader::RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader)
-{
- return 1;
-}
-
-//----------------------------------------------------------------------------
-int vtkGDCMPolyDataReader::RequestInformation(
- vtkInformation *vtkNotUsed(request),
- vtkInformationVector **vtkNotUsed(inputVector),
- vtkInformationVector *outputVector)
-{
- // get the info object
-// vtkInformation *outInfo = outputVector->GetInformationObject(0);
-//
-// outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
-// -1);
- gdcm::Reader reader;
- reader.SetFileName( this->FileName );
- if( !reader.Read() )
- {
- return 0;
- }
-
- gdcm::MediaStorage ms;
- ms.SetFromFile( reader.GetFile() );
-
- int ret;
- if( ms == gdcm::MediaStorage::RTStructureSetStorage )
- {
- ret = this->RequestInformation_RTStructureSetStorage(reader);
- }
- else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage)
- {
- ret = this->RequestInformation_HemodynamicWaveformStorage(reader);
- }
- else
- {
- // not handled assume error
- ret = 0;
- }
-
- if( ret )
- {
- // Ok let's fill in the 'extra' info:
- this->FillMedicalImageInformation(reader);
- }
-
- return ret;
-}
-
-
-//----------------------------------------------------------------------------
-void vtkGDCMPolyDataReader::PrintSelf(ostream& os, vtkIndent indent)
-{
- this->Superclass::PrintSelf(os,indent);
-
- os << indent << "File Name: "
- << (this->FileName ? this->FileName : "(none)") << "\n";
-
-
-}
+++ /dev/null
-/*=========================================================================
- Program: vv http://www.creatis.insa-lyon.fr/rio/vv
-
- Authors belong to:
- - University of LYON http://www.universite-lyon.fr/
- - Léon Bérard cancer center http://www.centreleonberard.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 See included LICENSE.txt file
- - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================*/
-/*=========================================================================
-
- Program: GDCM (Grassroots DICOM). A DICOM library
-
- Copyright (c) 2006-2011 Mathieu Malaterre
- All rights reserved.
- See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-// .NAME vtkGDCMPolyDataReader - read DICOM PolyData files (Contour Data...)
-// .SECTION Description
-// For now only support RTSTRUCT (RT Structure Set Storage)
-// .SECTION TODO
-// Need to do the same job for DVH Sequence/DVH Data...
-// .SECTION Warning
-// When using vtkGDCMPolyDataReader in conjonction with vtkGDCMImageReader
-// it is *required* that FileLowerLeft is set to ON as coordinate system
-// would be inconsistant in between the two data structures.
-//
-// .SECTION See Also
-// vtkGDCMImageReader vtkGDCMPolyDataWriter vtkRTStructSetProperties
-
-
-#ifndef VTKGDCMPOLYDATAREADER_H
-#define VTKGDCMPOLYDATAREADER_H
-
-#include "vtkPolyDataAlgorithm.h"
-
-class vtkMedicalImageProperties;
-class vtkRTStructSetProperties;
-//BTX
-namespace gdcm { class Reader; }
-//ETX
-class VTK_EXPORT vtkGDCMPolyDataReader : public vtkPolyDataAlgorithm
-{
-public:
- static vtkGDCMPolyDataReader *New();
- vtkTypeRevisionMacro(vtkGDCMPolyDataReader,vtkPolyDataAlgorithm);
- virtual void PrintSelf(ostream& os, vtkIndent indent);
-
- // Description:
- // Set/Get the filename of the file to be read
- vtkSetStringMacro(FileName);
- vtkGetStringMacro(FileName);
-
- // Description:
- // Get the medical image properties object
- vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties);
-
- vtkGetObjectMacro(RTStructSetProperties, vtkRTStructSetProperties);
-
-protected:
- vtkGDCMPolyDataReader();
- ~vtkGDCMPolyDataReader();
-
- char *FileName;
- vtkMedicalImageProperties *MedicalImageProperties;
- vtkRTStructSetProperties *RTStructSetProperties;
-//BTX
- void FillMedicalImageInformation(const gdcm::Reader &reader);
-//ETX
-
- int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
- int RequestInformation(
- vtkInformation *vtkNotUsed(request),
- vtkInformationVector **vtkNotUsed(inputVector),
- vtkInformationVector *outputVector);
-//BTX
- int RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader);
- int RequestData_RTStructureSetStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector);
- int RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader);
- int RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector);
-//ETX
-
-private:
- vtkGDCMPolyDataReader(const vtkGDCMPolyDataReader&); // Not implemented.
- void operator=(const vtkGDCMPolyDataReader&); // Not implemented.
-};
-
-#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://www.centreleonberard.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 See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKBINARYIMAGETOMESHFILTER_H
+#define CLITKMESHTOBINARYIMAGEFILTER_H
+
+// clitk
+#include "clitkCommon.h"
+#include "vvFromITK.h"
+
+// itk
+#include <itkProcessObject.h>
+
+// vtk
+#include <vtkSmartPointer.h>
+#include <vtkPolyData.h>
+#include <vtkImageClip.h>
+#include <vtkMarchingSquares.h>
+#include <vtkAppendPolyData.h>
+#include <vtkDecimatePro.h>
+#include <vtkStripper.h>
+
+namespace clitk {
+
+ /* --------------------------------------------------------------------
+ Convert a 3D binary image into a list of 2D contours (vtkpolydata)
+ -------------------------------------------------------------------- */
+
+ template<class ImageType>
+ class ITK_EXPORT BinaryImageToMeshFilter:public itk::Object //:public clitk::FilterBase
+ {
+
+ public:
+ /** Standard class typedefs. */
+ // typedef itk::ImageToMeshFilter<ImageType, vtkPolyData> Superclass;
+ typedef itk::ProcessObject Superclass;
+ typedef BinaryImageToMeshFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(BinaryImageToMeshFilter, Superclass);
+
+ /** ImageDimension constants */
+ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+
+ // /** Some convenient typedefs. */
+ // typedef typename ImageType::ConstPointer ImageConstPointer;
+ typedef typename ImageType::Pointer ImagePointer;
+ // typedef typename ImageType::RegionType RegionType;
+ typedef typename ImageType::PixelType PixelType;
+ // typedef typename ImageType::SpacingType SpacingType;
+ // typedef typename ImageType::SizeType SizeType;
+ // typedef typename ImageType::PointType PointType;
+ //typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType;
+ // typedef vtkSmartPointer<vtkPolyData> DataObjectPointer;
+
+ // using Superclass::SetInput;
+ // void SetInput(unsigned int idx, const ImageType *input);
+ // void SetInput(const ImageType *input)
+ // {
+ // m_this->SetInput(0, input);
+ // }
+
+ // const ImageType * GetInput(unsigned int idx);
+ // const ImageType * GetInput()
+ // {
+ // return this->GetInput(0);
+ // }
+
+ //virtual DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx);
+ // virtual void GenerateData();
+ // virtual void GenerateOutputInformation();
+
+ /** Input : initial image and object */
+ // itkSetMacro(Mesh, vtkSmartPointer<vtkPolyData>);
+ // itkGetConstMacro(Mesh, vtkSmartPointer<vtkPolyData>);
+
+ // itkSetMacro(LikeImage, ImagePointer);
+ // itkGetConstMacro(LikeImage, ImagePointer);
+
+ // itkSetMacro(Extrude, bool);
+ // itkGetMacro(Extrude, bool);
+ // itkBooleanMacro(Extrude);
+ itkSetMacro(Input, ImagePointer);
+ itkGetConstMacro(Input, ImagePointer);
+ itkGetMacro(OutputMesh, vtkSmartPointer<vtkPolyData>);
+
+ // virtual void GenerateOutputInformation();
+ virtual void Update();
+
+ protected:
+ BinaryImageToMeshFilter();
+ virtual ~BinaryImageToMeshFilter() {}
+
+ ImagePointer m_Input;
+ vtkSmartPointer<vtkPolyData> m_OutputMesh;
+
+ private:
+ BinaryImageToMeshFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkBinaryImageToMeshFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://www.centreleonberard.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 See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+clitk::BinaryImageToMeshFilter<ImageType>::
+BinaryImageToMeshFilter()//:ProcessObject()
+{
+ DD("BinaryImageToMeshFilter constructor");
+ // this->ProcessObject::SetNumberOfRequiredInputs(1);
+ // this->ProcessObject::SetNumberOfRequiredOutputs(1);
+
+ // //m_OutputMesh = vtkPolyData::New();
+
+ // this->ProcessObject::SetNumberOfRequiredOutputs(1);
+ // itk::DataObject::Pointer a = itk::DataObject::New();
+ // this->ProcessObject::SetNthOutput( 0, a);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+/*template <class ImageType>
+ void
+ clitk::BinaryImageToMeshFilter<ImageType>::
+ GenerateOutputInformation()
+ {
+ DD("GenerateOutputInformation");
+ // ImagePointer output = this->GetOutput(0);
+
+ // // Set the region to output
+ // typename ImageType::RegionType m_Region = m_LikeImage->GetLargestPossibleRegion();
+ // typename ImageType::SizeType size = m_Region.GetSize();
+ // size[0]++;
+ // size[1]++;
+ // size[2]++;
+ // m_Region.SetSize(size);
+ // output->SetLargestPossibleRegion(m_Region);
+ // output->SetRequestedRegion(m_Region);
+ // output->SetBufferedRegion(m_Region);
+ // output->SetRegions(m_Region);
+ // output->Allocate();
+ }
+*/
+//--------------------------------------------------------------------
+
+
+// template <class ImageType>
+// void
+// clitk::BinaryImageToMeshFilter<ImageType>::
+// SetInput(unsigned int idx, const ImageType *input)
+// {
+// DD(idx);
+// // process object is not const-correct, the const_cast
+// // is required here.
+// this->ProcessObject::SetNthInput( idx,
+// const_cast< ImageType * >( input ) );
+// DD("end");
+// }
+
+// template <class ImageType>
+// const ImageType *
+// clitk::BinaryImageToMeshFilter<ImageType>::
+// GetInput(unsigned int idx)
+// {
+// DD("GetInput");
+// DD(idx);
+// return dynamic_cast< const ImageType * >
+// ( this->ProcessObject::GetInput(idx) );
+// }
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::BinaryImageToMeshFilter<ImageType>::
+Update()
+//GenerateOutputInformation()
+{
+ DD("Update");
+
+ // Convert itk image into vtk image
+ const ImageType * im = this->GetInput();
+ typedef itk::ImageToVTKImageFilter<ImageType> ConvertType;
+ typename ConvertType::Pointer convert = ConvertType::New();
+ convert->SetInput(im);
+ convert->Update();
+ vtkImageData * input_vtk = convert->GetOutput();
+
+ // Get extend
+ vtkSmartPointer<vtkImageClip> clipper = vtkSmartPointer<vtkImageClip>::New();
+ clipper->SetInput(input_vtk);
+ int* extent = input_vtk->GetExtent();
+ DDV(extent, 6);
+
+ // Loop on slices
+ vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();
+ uint n = input_vtk->GetDimensions()[2];
+ DD(n);
+ std::vector<vtkSmartPointer<vtkPolyData> > contours;
+ for(uint i=0; i<n; i++) {
+ DD(i);
+ // FIXME vtkDiscreteMarchingCubes INSTEAD ?
+ vtkSmartPointer<vtkMarchingSquares> squares = vtkSmartPointer<vtkMarchingSquares>::New();
+ squares->SetInput(input_vtk);
+ squares->SetImageRange(extent[0], extent[1], extent[2], extent[3], i, i);
+ squares->SetNumberOfContours(1);
+ squares->SetValue(0, 0.5); // FIXME background (?)
+ squares->Update();
+ // DD(squares->GetNumberOfContours());
+
+ vtkSmartPointer<vtkPolyData> m = squares->GetOutput();
+
+ DD(m->GetMaxCellSize());
+ DD(m->GetNumberOfVerts());
+ DD(m->GetNumberOfLines());
+ DD(m->GetNumberOfPolys());
+ DD(m->GetNumberOfStrips());
+
+ // Decimate
+ if (false) { // FIXME
+ vtkSmartPointer<vtkDecimatePro> psurface = vtkDecimatePro::New();
+ psurface->SetInputConnection(squares->GetOutputPort());
+ psurface->SetTargetReduction(0.5);
+ psurface->Update();
+ m = psurface->GetOutput();
+ }
+ if (true) {
+ vtkSmartPointer<vtkStripper> vs = vtkSmartPointer<vtkStripper>::New();
+ vs->SetInput(squares->GetOutput());
+ vs->Update();
+ m = vs->GetOutput();
+ }
+
+ //vtkSmartPointer<vtkPolyData> m = squares->GetOutput();
+ contours.push_back(m);
+ DD(m->GetMaxCellSize());
+ DD(m->GetNumberOfVerts());
+ DD(m->GetNumberOfLines());
+ DD(m->GetNumberOfPolys());
+ DD(m->GetNumberOfStrips());
+ // m->Print(std::cout);
+
+ // FIXME : only add if lines>0
+ if (m->GetNumberOfLines() > 0) {
+ append->AddInput(contours[i]);
+ }
+ }
+ DD("done");
+
+ DD("now append");
+ // for(unsigned int i=0; i<n; i++) {
+ // append->AddInput(contours[i]);
+ // }
+ append->Update();
+
+ DD(" copy");
+ m_OutputMesh = vtkSmartPointer<vtkPolyData>::New();
+ m_OutputMesh->DeepCopy(append->GetOutput());
+
+ /* // NO (3D)
+ vtkSmartPointer<vtkContourFilter> pcontour = vtkContourFilter::New();
+ pcontour->SetValue(0, 0.5);
+ pcontour->SetInput(input_vtk);
+ pcontour->Update();
+ // vtkAlgorithmOutput *data = pcontour->GetOutputPort();
+ // vtkSmartPointer<vtkPolyDataMapper> skinMapper = vtkPolyDataMapper::New();
+ // skinMapper->SetInputConnection(data); //psurface->GetOutputPort()
+ // skinMapper->ScalarVisibilityOff();
+ m_OutputMesh = pcontour->GetOutput();//data
+ */
+
+ DD("end");
+ int a=12;
+ DD("erelre");
+}
+//--------------------------------------------------------------------
+
m_size[GetDirection()] = 0;
m_region.SetSize(m_size);
int start = m_index[GetDirection()];
+#if ITK_VERSION_MAJOR >= 4
+ this->SetNumberOfIndexedInputs(m_NumberOfSlices);
+#else
this->SetNumberOfOutputs(m_NumberOfSlices);
- // deprecated : use SetNumberOfIndexedInputs ? FIXME
+#endif
//--------------------------------------------------------------------
// loop ExtractImageFilter with region updated, push_back
option "spacinglike" - "New output spacing like this image" string no
option "origin" - "New output origin if different from input" double no multiple
option "matrix" m "Affine matrix (homogene) filename" string no
-option "elastix" e "Read EulerTransform from elastix output file" string no
+option "elastix" e "Read EulerTransform from elastix output file (combine if multiple)" string no multiple
option "rotate" r "Rotation to apply (radians)" double no multiple
option "translate" t "Translation to apply (mm)" double no multiple
option "pad" - "Edge padding value" double no default="0.0"
template<unsigned int Dimension, class PixelType>
typename itk::Matrix<double, Dimension+1, Dimension+1>
- createMatrixFromElastixFile(std::string filename);
+ createMatrixFromElastixFile(std::vector<std::string> & filename);
bool GetElastixValueFromTag(std::ifstream & is, std::string tag, std::string & value);
void GetValuesFromValue(const std::string & s,
// Call UpdateWithDim
if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
else
- if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
- else if (Dimension==4)UpdateWithDim<4>(PixelType, Components);
- else {
- std::cout<<"Error, Only for 2, 3 or 4 Dimensions!!!"<<std::endl ;
- return;
- }
+ if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
+ else if (Dimension==4)UpdateWithDim<4>(PixelType, Components);
+ else {
+ std::cout<<"Error, Only for 2, 3 or 4 Dimensions!!!"<<std::endl ;
+ return;
+ }
}
//-------------------------------------------------------------------
if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
UpdateWithDimAndPixelType<Dimension, signed short>();
}
- // else if(PixelType == "unsigned_short"){
- // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
- // UpdateWithDimAndPixelType<Dimension, unsigned short>();
- // }
+ else if(PixelType == "unsigned_short"){
+ if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+ UpdateWithDimAndPixelType<Dimension, unsigned short>();
+ }
else if (PixelType == "unsigned_char") {
if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
}
else {
if (m_ArgsInfo.elastix_given) {
- matrix = createMatrixFromElastixFile<Dimension,PixelType>(m_ArgsInfo.elastix_arg);
+ std::vector<std::string> s;
+ for(uint i=0; i<m_ArgsInfo.elastix_given; i++) s.push_back(m_ArgsInfo.elastix_arg[i]);
+ matrix = createMatrixFromElastixFile<Dimension,PixelType>(s);
}
else
matrix.SetIdentity();
template<class args_info_type>
template<unsigned int Dimension, class PixelType>
typename itk::Matrix<double, Dimension+1, Dimension+1>
- AffineTransformGenericFilter<args_info_type>::createMatrixFromElastixFile(std::string filename)
+ AffineTransformGenericFilter<args_info_type>::createMatrixFromElastixFile(std::vector<std::string> & filename)
{
if (Dimension != 3) {
FATAL("Only 3D yet" << std::endl);
}
typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
- // Open file
- std::ifstream is;
- clitk::openFileForReading(is, filename);
-
- // Check Transform
- std::string s;
- bool b = GetElastixValueFromTag(is, "Transform ", s);
- if (!b) {
- FATAL("Error must read 'Transform' in " << filename << std::endl);
- }
- if (s != "EulerTransform") {
- FATAL("Sorry only 'EulerTransform'" << std::endl);
- }
-
- // FIXME check
- // (InitialTransformParametersFileName "NoInitialTransform")
-
- // Get CenterOfRotationPoint
- GetElastixValueFromTag(is, "CenterOfRotationPoint ", s); // space is needed
- if (!b) {
- FATAL("Error must read 'CenterOfRotationPoint' in " << filename << std::endl);
- }
- std::vector<std::string> cor;
- GetValuesFromValue(s, cor);
-
- // Get Transformparameters
- GetElastixValueFromTag(is, "TransformParameters ", s); // space is needed
- if (!b) {
- FATAL("Error must read 'TransformParameters' in " << filename << std::endl);
- }
- std::vector<std::string> results;
- GetValuesFromValue(s, results);
-
- // construct a stream from the string
itk::CenteredEuler3DTransform<double>::Pointer mat = itk::CenteredEuler3DTransform<double>::New();
- itk::CenteredEuler3DTransform<double>::ParametersType p;
- p.SetSize(9);
- for(uint i=0; i<3; i++)
- p[i] = atof(results[i].c_str()); // Rotation
- for(uint i=0; i<3; i++)
- p[i+3] = atof(cor[i].c_str()); // Centre of rotation
- for(uint i=0; i<3; i++)
- p[i+6] = atof(results[i+3].c_str()); // Translation
- mat->SetParameters(p);
+ itk::CenteredEuler3DTransform<double>::Pointer previous;
+ for(uint j=0; j<filename.size(); j++) {
+
+ // Open file
+ if (m_Verbose) std::cout << "Read elastix parameters in " << filename[j] << std::endl;
+ std::ifstream is;
+ clitk::openFileForReading(is, filename[j]);
+
+ // Check Transform
+ std::string s;
+ bool b = GetElastixValueFromTag(is, "Transform ", s);
+ if (!b) {
+ FATAL("Error must read 'Transform' in " << filename[j] << std::endl);
+ }
+ if (s != "EulerTransform") {
+ FATAL("Sorry only 'EulerTransform'" << std::endl);
+ }
+
+ // FIXME check
+ // (InitialTransformParametersFilename[j] "NoInitialTransform")
+
+ // Get CenterOfRotationPoint
+ GetElastixValueFromTag(is, "CenterOfRotationPoint ", s); // space is needed
+ if (!b) {
+ FATAL("Error must read 'CenterOfRotationPoint' in " << filename[j] << std::endl);
+ }
+ std::vector<std::string> cor;
+ GetValuesFromValue(s, cor);
+
+ // Get Transformparameters
+ GetElastixValueFromTag(is, "TransformParameters ", s); // space is needed
+ if (!b) {
+ FATAL("Error must read 'TransformParameters' in " << filename[j] << std::endl);
+ }
+ std::vector<std::string> results;
+ GetValuesFromValue(s, results);
+
+ // construct a stream from the string
+ itk::CenteredEuler3DTransform<double>::ParametersType p;
+ p.SetSize(9);
+ for(uint i=0; i<3; i++)
+ p[i] = atof(results[i].c_str()); // Rotation
+ for(uint i=0; i<3; i++)
+ p[i+3] = atof(cor[i].c_str()); // Centre of rotation
+ for(uint i=0; i<3; i++)
+ p[i+6] = atof(results[i+3].c_str()); // Translation
+ mat->SetParameters(p);
- if (m_Verbose) {
- std::cout << "Rotation (deg) : " << rad2deg(p[0]) << " " << rad2deg(p[1]) << " " << rad2deg(p[2]) << std::endl;
- std::cout << "Translation (phy) : " << p[3] << " " << p[4] << " " << p[5] << std::endl;
- std::cout << "Center of rot (phy) : " << p[6] << " " << p[7] << " " << p[8] << std::endl;
+ if (m_Verbose) {
+ std::cout << "Rotation (deg) : " << rad2deg(p[0]) << " " << rad2deg(p[1]) << " " << rad2deg(p[2]) << std::endl;
+ std::cout << "Center of rot (phy) : " << p[3] << " " << p[4] << " " << p[5] << std::endl;
+ std::cout << "Translation (phy) : " << p[6] << " " << p[7] << " " << p[8] << std::endl;
+ }
+
+ // Compose with previous if needed
+ if (j!=0) {
+ mat->Compose(previous);
+ if (m_Verbose) {
+ std::cout << "Composed rotation (deg) : " << rad2deg(mat->GetAngleX()) << " " << rad2deg(mat->GetAngleY()) << " " << rad2deg(mat->GetAngleZ()) << std::endl;
+ std::cout << "Composed center of rot (phy) : " << mat->GetCenter() << std::endl;
+ std::cout << "Compsoed translation (phy) : " << mat->GetTranslation() << std::endl;
+ }
+ }
+ previous = mat->Clone();
}
+ mat = previous;
for(uint i=0; i<3; i++)
for(uint j=0; j<3; j++)
matrix[i][j] = mat->GetMatrix()[i][j];
value.erase (std::remove (value.begin(), value.end(), ')'), value.end());
return true;
}
- }
+ }
return false;
}
//-------------------------------------------------------------------
vvToolBinarize
vvToolImageArithm
vvToolResample
-# vvToolExtractPatient
-# vvToolExtractLung
- vvToolStructureSetManager
vvToolMIP
vvToolConvert ## with dummy vvToolConvert.ui
vvToolROIManager
vvToolSegmentation
-
## these ones are for tests (not working)
# vvToolFoo
# vvToolFooWithWidgetBase
# vvToolPlastimatch
# vvToolConnectedComponentLabeling
+ ## these ones are old ones
+ # vvToolExtractPatient
+ # vvToolExtractLung
+ # vvToolStructureSetManager
)
# dependencies of the tools
# Future issues : when tool depend on other tools ... how to manage that ?
SET(vvToolMIP_LIBS clitkMIPLib)
SET(vvToolMedianFilter_LIBS clitkMedianImageFilterLib)
SET(vvToolImageArithm_LIBS clitkImageArithmImageLib)
+SET(vvToolROIManager_LIBS clitkDicomRTStruct)
#=========================================================
# List of vv source files
)
LINK_DIRECTORIES(${QT_LIBRARY_DIR})
+
#=========================================================
#Add each tool's dependencies
foreach(tool ${vv_TOOLS})
SET(toolLibs ${toolLibs} ${${tool}_LIBS})
endforeach(tool)
+
#=========================================================
#Add Foundation Libraries (this should be after our libraries, since we depend
#on them)
#=========================================================
#Create binary and libs for tests
-SET(vvExternalLibs ${QT_QTNETWORK_LIBRARY} clitkSegmentationGgoLib clitkDicomRTStruct ${toolLibs} ${foundationLibraries} ${vvCxImage})
+SET(vvExternalLibs ${QT_QTNETWORK_LIBRARY} clitkSegmentationGgoLib ${toolLibs} ${foundationLibraries} ${vvCxImage})
# QtNetwork is required by vvRegisterForm
ADD_LIBRARY(vvLib ${vv_SRCS} ${vv_UI_CXX})
ADD_EXECUTABLE(vv vv.cxx)
ENDIF(WIN32)
-#TARGET_LINK_LIBRARIES(vv vvLib)
-TARGET_LINK_LIBRARIES(vv vvLib)
-
+TARGET_LINK_LIBRARIES(vv vvLib ${CLITK_GDCM_LIBRARIES})
#=========================================================
# Install options (also used by CPack)
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">space</span><span style=" font-size:12pt;">: Landmark</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Navigation</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">r</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">R</span><span style=" font-size:12pt;">eset View</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">u</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">U</span><span style=" font-size:12pt;">pdate Image</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">f</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">F</span><span style=" font-size:12pt;">ly To Mouse Position</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">g</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">G</span><span style=" font-size:12pt;">o to Crosshair Position</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Ctrl+g</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">G</span><span style=" font-size:12pt;">o to Coordinate System Origin</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">h</span><span style=" font-size:12pt;">: </span><span style=" font-size:12pt; text-decoration: underline;">H</span><span style=" font-size:12pt;">ide Crosshair and corner annotations</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Up,Down</span><span style=" font-size:12pt;">: Change Slice</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Left, Right</span><span style=" font-size:12pt;">: Change Temporal Slice</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Tab</span><span style=" font-size:12pt;">: Change image</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">Mouse</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">i/o or Ctrl+Wheel</span><span style=" font-size:12pt;">: Zoom </span><span style=" font-size:12pt; text-decoration: underline;">I</span><span style=" font-size:12pt;">n/</span><span style=" font-size:12pt; text-decoration: underline;">O</span><span style=" font-size:12pt;">ut</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Left Button</span><span style=" font-size:12pt;">: Synchronize All Views</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Middle Button</span><span style=" font-size:12pt;">: Grab Image</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Right Button</span><span style=" font-size:12pt;">: Change Windowing</span></p></body></html></string>
+</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">space</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Landmark</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:12pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600; text-decoration: underline;">Navigation</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:12pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">r</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">R</span><span style=" font-family:'Sans Serif'; font-size:12pt;">eset View</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">u</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">U</span><span style=" font-family:'Sans Serif'; font-size:12pt;">pdate Image</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">f</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">F</span><span style=" font-family:'Sans Serif'; font-size:12pt;">ly To Mouse Position</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">g</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">G</span><span style=" font-family:'Sans Serif'; font-size:12pt;">o to Crosshair Position</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Ctrl+g</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">G</span><span style=" font-family:'Sans Serif'; font-size:12pt;">o to Coordinate System Origin</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">h</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">H</span><span style=" font-family:'Sans Serif'; font-size:12pt;">ide Crosshair and corner annotations</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:12pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Up,Down</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Change Slice</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Left, Right</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Change Temporal Slice</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Tab</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Change image</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:12pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600; text-decoration: underline;">Mouse</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:12pt;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">i/o or Ctrl+Wheel</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Zoom </span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">I</span><span style=" font-family:'Sans Serif'; font-size:12pt;">n/</span><span style=" font-family:'Sans Serif'; font-size:12pt; text-decoration: underline;">O</span><span style=" font-family:'Sans Serif'; font-size:12pt;">ut</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Left Button</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Synchronize All Views</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Middle Button (or shift on mac)</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Grab Image</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:12pt; font-weight:600;">Right Button</span><span style=" font-family:'Sans Serif'; font-size:12pt;">: Change Windowing</span></p></body></html></string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<x>0</x>
<y>0</y>
<width>1008</width>
- <height>18</height>
+ <height>20</height>
</rect>
</property>
<property name="defaultUp">
<addaction name="actionOpen_Multiple_Images_As_One"/>
<addaction name="separator"/>
<addaction name="actionOpen_Dicom"/>
- <addaction name="actionOpen_Dicom_Struct"/>
<addaction name="actionOpen_VTK_contour"/>
<addaction name="separator"/>
<addaction name="actionSave_As"/>
connect(actionWarp_image_with_vector_field,SIGNAL(triggered()),this,SLOT(WarpImage()));
connect(actionLoad_images,SIGNAL(triggered()),this,SLOT(OpenImages()));
connect(actionOpen_Dicom,SIGNAL(triggered()),this,SLOT(OpenDicom()));
- connect(actionOpen_Dicom_Struct,SIGNAL(triggered()),this,SLOT(OpenDCStructContour()));
+ // connect(actionOpen_Dicom_Struct,SIGNAL(triggered()),this,SLOT(OpenDCStructContour()));
connect(actionOpen_VTK_contour,SIGNAL(triggered()),this,SLOT(OpenVTKContour()));
connect(actionOpen_Multiple_Images_As_One,SIGNAL(triggered()),this,SLOT(MergeImages()));
connect(actionSlice_Image_As_Multiple_Images,SIGNAL(triggered()),this,SLOT(SliceImages()));
brush.setColor(QColor(contour->r*255,contour->g*255,contour->b*255));
brush.setStyle(Qt::SolidPattern);
item->setData(COLUMN_IMAGE_NAME,Qt::BackgroundRole,brush);
- item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,contour->structure_name.c_str());
+ // item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,contour->structure_name.c_str());
for (int j = 1; j <= 4; j++)
item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(image_index)->data(j,Qt::CheckStateRole));
- BSD See included LICENSE.txt file
- CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================**/
+ ===========================================================================**/
+
+// std
#include <algorithm>
+// qt
#include <QApplication>
+// gdcm
#include <gdcmFile.h>
#if GDCM_MAJOR_VERSION == 2
- #include <gdcmReader.h>
- #include <gdcmTag.h>
- #include <gdcmAttribute.h>
+#include <gdcmReader.h>
+#include <gdcmTag.h>
+#include <gdcmAttribute.h>
#else
- #include <gdcm.h>
- #include <gdcmSQItem.h>
+#include <gdcm.h>
+#include <gdcmSQItem.h>
#endif
+// vtk
#include <vtkSmartPointer.h>
#include <vtkAppendPolyData.h>
#include <vtkCellArray.h>
#include <vtkImageCast.h>
#include <vtkImageGaussianSmooth.h>
+// clitk
+#include "clitkCommon.h"
#include "clitkCommon.h"
+#include "clitkDicomRT_StructureSet.h"
#include "vvMeshReader.h"
#include "vvProgressDialog.h"
-#include <clitkCommon.h>
+//------------------------------------------------------------------------------
vvMeshReader::vvMeshReader() :
- vtk_mode(false)
+vtk_mode(false)
{}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
void vvMeshReader::Update()
{
//Show a progress bar only when opening a DC-struct (ie. multiple contours)
qApp->processEvents();
}
}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
void vvMeshReader::run()
{
///Verify the important stuff has been set
}
}
}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
std::vector<std::pair<int,std::string> > vvMeshReader::GetROINames()
{
assert(filename!="");
std::vector<std::pair<int, std::string> > roi_names;
-#if GDCM_MAJOR_VERSION == 2
- // duplicate code from clitk::DicomRT_StructureSet::Read
- gdcm::Reader reader;
- reader.SetFileName( filename.c_str() );
- reader.Read();
- const gdcm::DataSet &ds = reader.GetFile().GetDataSet();
+#if CLITK_USE_SYSTEM_GDCM == 1
- gdcm::Tag tssroisq(0x3006,0x0020);
- const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
- gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ssroisq.GetValueAsSQ();
- assert(roi_seq); // TODO error message
- for(unsigned int ridx = 0; ridx < roi_seq->GetNumberOfItems(); ++ridx)
- {
- gdcm::Item & item = roi_seq->GetItem( ridx + 1); // Item starts at 1
- const gdcm::DataSet& nestedds = item.GetNestedDataSet();
- if( nestedds.FindDataElement( gdcm::Tag(0x3006,0x22) ) )
+ // Read RT-struct data
+ vtkSmartPointer<vtkGDCMPolyDataReader> areader = vtkGDCMPolyDataReader::New();
+ areader->SetFileName(filename.c_str());
+ areader->Update();
+
+ // get info on roi names
+ vtkRTStructSetProperties * p = areader->GetRTStructSetProperties();
+ int n = p->GetNumberOfStructureSetROIs();
+
+ for(unsigned int i=0; i<n; i++) {
+ std::string name = p->GetStructureSetROIName(i);
+ int nb = p->GetStructureSetROINumber(i);
+ roi_names.push_back(make_pair(nb,name));
+ }
+
+#else
+#if GDCM_MAJOR_VERSION == 2
+
+ // duplicate code from clitk::DicomRT_StructureSet::Read
+ gdcm::Reader * reader = new gdcm::Reader;
+ reader->SetFileName( filename.c_str() );
+ reader->Read();
+
+ const gdcm::DataSet &ds = reader->GetFile().GetDataSet();
+
+ // Check file type
+ //Verify if the file is a RT-Structure-Set dicom file
+ gdcm::File * mFile = &(reader->GetFile());
+ gdcm::MediaStorage ms;
+ ms.SetFromFile(*mFile);
+ if( ms != gdcm::MediaStorage::RTStructureSetStorage )
+ {
+ 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);
+ }
+
+ gdcm::Attribute<0x8,0x60> modality;
+ modality.SetFromDataSet( ds );
+ if( modality.GetValue() != "RTSTRUCT" )
{
- gdcm::Attribute<0x3006,0x26> roiname;
- roiname.SetFromDataSet( nestedds );
- std::string name = roiname.GetValue(); // 0x3006,0x0026 = [ROI Name]
- gdcm::Attribute<0x3006,0x0022> roinumber;
- roinumber.SetFromDataSet( nestedds );
- int nb = roinumber.GetValue(); // 0x3006,0x0022 = [ROI Number]
-
- roi_names.push_back(make_pair(nb,name));
+ std::cerr << "Error. the file " << filename
+ << " is not a Dicom Struct ? (must have 0x0008,0x0060 = RTSTRUCT [RT Structure Set Storage])"
+ << std::endl;
+ exit(0);
}
+
+ gdcm::Attribute<0x20,0x10> studyid;
+ studyid.SetFromDataSet( ds );
+
+ gdcm::Tag tssroisq(0x3006,0x0020);
+ // 0x3006,0x0020 = [ Structure Set ROI Sequence ]
+ bool b = ds.FindDataElement(tssroisq);
+ if (!b) { // FIXME
+ clitkExceptionMacro("Error: tag 0x3006,0x0020 [ Structure Set ROI Sequence ] not found");
}
+
+ const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq );
+ gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ssroisq.GetValueAsSQ();
+ assert(roi_seq); // FIXME error message
+
+ for(unsigned int ridx = 0; ridx < roi_seq->GetNumberOfItems(); ++ridx)
+ {
+ gdcm::Item & item = roi_seq->GetItem( ridx + 1); // Item starts at 1
+
+ const gdcm::Item & sitem = roi_seq->GetItem(ridx+1); // Item start at #1
+
+ const gdcm::DataSet& snestedds = sitem.GetNestedDataSet();
+ const gdcm::DataSet& nestedds = item.GetNestedDataSet();
+
+ if( snestedds.FindDataElement( gdcm::Tag(0x3006,0x22) ) )
+ {
+ // const gdcm::DataElement & a = nestedds.GetDataElement(gdcm::Tag(0x3006,0x26));
+ // DD(a.GetValue());
+
+ gdcm::Attribute<0x3006,0x26> roiname;
+ roiname.SetFromDataSet( snestedds );
+ std::string name = roiname.GetValue(); // 0x3006,0x0026 = [ROI Name]
+ gdcm::Attribute<0x3006,0x0022> roinumber;
+ roinumber.SetFromDataSet( snestedds );
+ int nb = roinumber.GetValue(); // 0x3006,0x0022 = [ROI Number]
+
+ roi_names.push_back(make_pair(nb,name));
+ }
+ }
+
+ delete reader;
+
#else
gdcm::File reader;
reader.SetFileName(filename.c_str());
if (i->GetEntryValue(0x3006,0x0022)!= gdcm::GDCM_UNFOUND)
roi_names.push_back(make_pair(atoi(i->GetEntryValue(0x3006,0x0022).c_str()),i->GetEntryValue(0x3006,0x0026)));
#endif
+#endif
+
return roi_names;
}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
std::vector<vvMesh::Pointer> vvMeshReader::readSelectedContours()
{
std::vector<vvMesh::Pointer> result;
#if GDCM_MAJOR_VERSION == 2
+
+#if CLITK_USE_SYSTEM_GDCM == 0
+
+ clitkExceptionMacro("ERROR ! You need to compile vv with itk4 + system_gdcm to use this function");
+
+#endif
+
gdcm::Reader reader;
reader.SetFileName(filename.c_str());
reader.Read();
assert(rois->GetNumberOfItems() == roi_info->GetNumberOfItems());
for (unsigned ridx = 0; ridx < rois->GetNumberOfItems(); ++ridx)
- {
- vtkSmartPointer<vtkAppendPolyData> append=vtkSmartPointer<vtkAppendPolyData>::New();
- const gdcm::DataSet& ds_rois = rois->GetItem( ridx + 1).GetNestedDataSet();
- const gdcm::DataSet& ds_roi_info = roi_info->GetItem( ridx + 1).GetNestedDataSet();
-
- gdcm::Attribute<0x3006,0x84> roinumber;
- roinumber.SetFromDataSet(ds_rois);
- if (std::find(selected_contours.begin(), selected_contours.end(), roinumber.GetValue()) != selected_contours.end()) //Only read selected ROIs
{
- gdcm::Attribute<0x3006,0x2a> trgb;
- trgb.SetFromDataSet(ds_rois);
- vvMesh::Pointer current_roi=vvMesh::New();
- current_roi->r = trgb[0] / 255.0;
- current_roi->g = trgb[1] / 255.0;
- current_roi->b = trgb[2] / 255.0;
+ vtkSmartPointer<vtkAppendPolyData> append=vtkSmartPointer<vtkAppendPolyData>::New();
+ const gdcm::DataSet& ds_rois = rois->GetItem( ridx + 1).GetNestedDataSet();
+ const gdcm::DataSet& ds_roi_info = roi_info->GetItem( ridx + 1).GetNestedDataSet();
- gdcm::Attribute<0x3006,0x26> tstructure_name;
- tstructure_name.SetFromDataSet(ds_roi_info);
- current_roi->structure_name = tstructure_name.GetValue();
+ gdcm::Attribute<0x3006,0x84> roinumber;
+ roinumber.SetFromDataSet(ds_rois);
+ if (std::find(selected_contours.begin(), selected_contours.end(), roinumber.GetValue()) != selected_contours.end()) //Only read selected ROIs
+ {
+ gdcm::Attribute<0x3006,0x2a> trgb;
+ trgb.SetFromDataSet(ds_rois);
+ vvMesh::Pointer current_roi=vvMesh::New();
+ current_roi->r = trgb[0] / 255.0;
+ current_roi->g = trgb[1] / 255.0;
+ current_roi->b = trgb[2] / 255.0;
- gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ds_rois.GetDataElement(gdcm::Tag(0x3006,0x40)).GetValueAsSQ();
- double z0=-1; //Used to determine spacing between slices, assumed to be constant
- for (unsigned j = 0; j < roi_seq->GetNumberOfItems(); ++j)
- {
- gdcm::Item & item_roi_seq = roi_seq->GetItem(j + 1); // Item starts at 1
- const gdcm::DataSet& ds_roi_seq = item_roi_seq.GetNestedDataSet();
- gdcm::Attribute<0x3006,0x42> tcontour_type;
- tcontour_type.SetFromDataSet(ds_roi_seq);
- std::string contour_type = tcontour_type.GetValue();
- if (contour_type=="CLOSED_PLANAR ")
+ gdcm::Attribute<0x3006,0x26> tstructure_name;
+ tstructure_name.SetFromDataSet(ds_roi_info);
+ current_roi->structure_name = tstructure_name.GetValue();
+
+ gdcm::SmartPointer<gdcm::SequenceOfItems> roi_seq = ds_rois.GetDataElement(gdcm::Tag(0x3006,0x40)).GetValueAsSQ();
+ double z0=-1; //Used to determine spacing between slices, assumed to be constant
+ for (unsigned j = 0; j < roi_seq->GetNumberOfItems(); ++j)
+ {
+ gdcm::Item & item_roi_seq = roi_seq->GetItem(j + 1); // Item starts at 1
+ const gdcm::DataSet& ds_roi_seq = item_roi_seq.GetNestedDataSet();
+ gdcm::Attribute<0x3006,0x42> tcontour_type;
+ tcontour_type.SetFromDataSet(ds_roi_seq);
+ std::string contour_type = tcontour_type.GetValue();
+ if (contour_type=="CLOSED_PLANAR ")
+ {
+ gdcm::Attribute<0x3006,0x46> tpoint_number;
+ tpoint_number.SetFromDataSet(ds_roi_seq);
+ const gdcm::DataElement & points_data = ds_roi_seq.GetDataElement(gdcm::Tag(0x3006,0x50));
+ gdcm::Attribute<0x3006,0x50> tpoints;
+ tpoints.SetFromDataElement(points_data);
+ assert(tpoints.GetNumberOfValues() == static_cast<unsigned int>(tpoint_number.GetValue()) * 3);
+ const double* points = tpoints.GetValues();
+ if (z0 == -1) //First contour
+ z0=points[2];
+ else
+ if (current_roi->GetSpacing()==-1 && points[2] != z0 )
+ current_roi->SetSpacing(points[2]-z0);
+ vtkPolyData * contour=vtkPolyData::New();
+ contour->Allocate(); //for cell structures
+ contour->SetPoints(vtkPoints::New());
+ vtkIdType ids[2];
+ for (unsigned idx = 0; idx < tpoints.GetNumberOfValues(); idx += 3)
+ {
+ contour->GetPoints()->InsertNextPoint(points[idx], points[idx+1], points[idx+2]);
+ ids[0] = idx / 3;
+ ids[1] = (ids[0] + 1) % tpoint_number.GetValue(); //0-1,1-2,...,n-1-0
+ contour->GetLines()->InsertNextCell(2, ids);
+ }
+ append->AddInput(contour);
+ }
+ else
+ if (contour_type == "POINT ")
+ ; // silently ignore POINT type since we don't need them at the moment
+ else
+ std::cerr << "Warning: contour type " << contour_type << " not handled!" << std::endl;
+ }
+ append->Update();
+ current_roi->AddMesh(append->GetOutput());
+ result.push_back(current_roi);
+ }
+ else
{
- gdcm::Attribute<0x3006,0x46> tpoint_number;
- tpoint_number.SetFromDataSet(ds_roi_seq);
- const gdcm::DataElement & points_data = ds_roi_seq.GetDataElement(gdcm::Tag(0x3006,0x50));
- gdcm::Attribute<0x3006,0x50> tpoints;
- tpoints.SetFromDataElement(points_data);
- assert(tpoints.GetNumberOfValues() == static_cast<unsigned int>(tpoint_number.GetValue()) * 3);
- const double* points = tpoints.GetValues();
- if (z0 == -1) //First contour
- z0=points[2];
- else
- if (current_roi->GetSpacing()==-1 && points[2] != z0 )
- current_roi->SetSpacing(points[2]-z0);
- vtkPolyData * contour=vtkPolyData::New();
- contour->Allocate(); //for cell structures
- contour->SetPoints(vtkPoints::New());
- vtkIdType ids[2];
- for (unsigned idx = 0; idx < tpoints.GetNumberOfValues(); idx += 3)
- {
- contour->GetPoints()->InsertNextPoint(points[idx], points[idx+1], points[idx+2]);
- ids[0] = idx / 3;
- ids[1] = (ids[0] + 1) % tpoint_number.GetValue(); //0-1,1-2,...,n-1-0
- contour->GetLines()->InsertNextCell(2, ids);
- }
- append->AddInput(contour);
+ //std::cerr << "Warning: ignoring ROI #" << roi_number << std::endl;
}
- else
- if (contour_type == "POINT ")
- ; // silently ignore POINT type since we don't need them at the moment
- else
- std::cerr << "Warning: contour type " << contour_type << " not handled!" << std::endl;
- }
- append->Update();
- current_roi->AddMesh(append->GetOutput());
- result.push_back(current_roi);
- }
- else
- {
- //std::cerr << "Warning: ignoring ROI #" << roi_number << std::endl;
}
- }
#else
gdcm::File reader;
reader.SetFileName(filename.c_str());
// STATIC
void vvToolROIManager::Initialize() {
SetToolName("ROIManager");
- SetToolMenuName("Display ROI (binary image)");
+ SetToolMenuName("Open ROI (binary image or RT-STRUCT)");
SetToolIconFilename(":/common/icons/tool-roi.png");
- SetToolTip("Display ROI from a binary image.");
+ SetToolTip("Display ROI from a binary image or a RT-struct file.");
SetToolExperimental(false);
}
//------------------------------------------------------------------------------
void vvToolROIManager::OpenBinaryImage(QStringList & filename)
{
if (filename.size() == 0) return;
-
+
vvProgressDialog p("Reading ROI ...", true);
p.SetCancelButtonEnabled(false);
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
// GUI selector of roi
vvMeshReader reader;
reader.SetFilename(filename);
+
vvStructSelector selector;
selector.SetStructures(reader.GetROINames());
selector.SetPropagationCheckBoxFlag(false);
// Loop on selected struct
std::vector<int> list = selector.getSelectedItems();
for (uint i=0; i<list.size(); i++) {
- p.SetProgress(i, list.size());
-
+ p.SetProgress(i, list.size());
+
clitk::DicomRTStruct2ImageFilter filter;
filter.SetCropMaskEnabled(true);
filter.SetImage(mCurrentImage);
//------------------------------------------------------------------------------
void vvToolROIManager::ReloadCurrentROI() {
+ if (mCurrentROI->GetImage()) {
+ return; // do nothing (contour from rt struct do not reload)
+ }
// Remove all contours/overlay first
bool visible = mCurrentROIActor->IsVisible();