/*========================================================================= 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 "vtkGDCMPolyDataWriter.h" #include "vtkGDCMPolyDataReader.h" #include "vtkPolyData.h" #include "vtkPolyDataReader.h" #include "vtkMedicalImageProperties.h" #include "vtkRTStructSetProperties.h" #include "vtkStringArray.h" #include "vtkAppendPolyData.h" #include "vtkPolyDataWriter.h" #include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper2D.h" #include "vtkActor2D.h" #include "vtkRenderWindowInteractor.h" #include "vtkMedicalImageProperties.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkImageData.h" #include //for std::find #include "gdcmDirectoryHelper.h" using namespace gdcm; //view each organ independently of the others, to make sure that //organ names correspond to actual segmentations. void ShowOrgan(vtkPolyData* inData) { // Now we'll look at it. vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputData( inData ); #else cubeMapper->SetInput( inData ); #endif 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(); cubeMapper->Delete(); cubeActor->Delete(); renderer->Delete(); renWin->Delete(); iren->Delete(); } /* * Full application which ... RTSTUCT */ int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " directory-with-rtstruct-and-ct-images\n"; return 1; } std::string theDirName(argv[1]); Directory::FilenamesType theRTSeries = DirectoryHelper::GetRTStructSeriesUIDs(theDirName); gdcm::Directory theDir; theDir.Load(argv[1]); if (theRTSeries.empty()) { std::cerr << "No RTStructs found for the test, ending." << std::endl; return 1; } for (size_t q = 0; q < theRTSeries.size(); q++) { Directory::FilenamesType theRTNames = DirectoryHelper::GetFilenamesFromSeriesUIDs(theDirName, theRTSeries[q]); if (theRTNames.empty()){ std::cerr << "Unable to load RT Series " << theRTSeries[q] << ", continuing. " << std::endl; continue; } vtkGDCMPolyDataReader * reader = vtkGDCMPolyDataReader::New(); reader->SetFileName( theRTNames[0].c_str() ); reader->Update(); //std::cout << reader->GetMedicalImageProperties()->GetStudyDate() << std::endl; vtkGDCMPolyDataWriter * writer = vtkGDCMPolyDataWriter::New(); int numMasks = reader->GetNumberOfOutputPorts() + 1;//add a blank one in writer->SetNumberOfInputPorts( numMasks ); std::string thePotentialName = theDirName + "/" + "GDCMTestRTStruct." + theRTSeries[q] + ".dcm"; gdcm::Directory::FilenamesType theFileNames = theDir.GetFilenames(); //keep renaming the output until we get something that doesn't overwrite what was there already int count = 0; while (std::find(theFileNames.begin(), theFileNames.end(), thePotentialName) != theFileNames.end()) { char buff[255]; sprintf(buff,"%d",count); thePotentialName = theDirName + "/" + "GDCMTestRTStruct." + buff + "." + theRTSeries[q] + ".dcm"; } writer->SetFileName( thePotentialName.c_str()); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); //this line is cheating, we won't have the same stuff, and may not have a struct //to start with. //have to go back to the original data to reconstruct the RTStructureSetProperties //writer->SetRTStructSetProperties( reader->GetRTStructSetProperties() ); //writer->Write(); //loop through the outputs in order to write them out as if they had been created and appended vtkStringArray* roiNames = vtkStringArray::New(); vtkStringArray* roiAlgorithms = vtkStringArray::New(); vtkStringArray* roiTypes = vtkStringArray::New(); roiNames->SetNumberOfValues(numMasks); roiAlgorithms->SetNumberOfValues(numMasks); roiTypes->SetNumberOfValues(numMasks); vtkAppendPolyData* append = vtkAppendPolyData::New(); //ok, now we'll add a blank organ //the blank organ is to test to ensure that blank organs work; there have been crash reports //this code is added at the beginning to ensure that the blank organs are read //and preserved as individual organs. vtkPolyData* blank = vtkPolyData::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData(0, blank); #else writer->SetInput(0, blank); #endif roiNames->InsertValue(0, "blank"); roiAlgorithms->InsertValue(0, "blank"); roiTypes->InsertValue(0, "ORGAN"); //note the offsets used to place the blank rtstruct at the beginning of the newly generated RT. //the idea is to run the program twice; first to generate an rtstruct with a blank mask (making //sure that that functionality works), and then a second time to make sure that everything is //being read properly. Multiple organs with the same name could cause some strangenesses. for (int i = 1; i < numMasks; ++i) { #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection(i, reader->GetOutputPort(i-1)); append->AddInputConnection(reader->GetOutputPort(i-1)); #else writer->SetInput(i, reader->GetOutput(i-1)); append->AddInput(reader->GetOutput(i-1)); #endif 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); ShowOrgan(reader->GetOutput(i-1)); } vtkRTStructSetProperties* theProperties = vtkRTStructSetProperties::New(); writer->SetRTStructSetProperties(theProperties); writer->InitializeRTStructSet(theDirName, reader->GetRTStructSetProperties()->GetStructureSetLabel(), reader->GetRTStructSetProperties()->GetStructureSetName(), roiNames, roiAlgorithms, roiTypes); writer->SetRTStructSetProperties(theProperties); writer->Write(); // print reader output: reader->Print( std::cout ); // print first output: reader->GetOutput()->Print( std::cout ); reader->Delete(); append->Delete(); roiNames->Delete(); roiTypes->Delete(); theProperties->Delete(); roiAlgorithms->Delete(); blank->Delete(); writer->Delete(); } return 0; }