diff --git a/Core/Code/Algorithms/mitkCoreObjectFactory.cpp b/Core/Code/Algorithms/mitkCoreObjectFactory.cpp index bea24d37eb..78aa9e6ce1 100755 --- a/Core/Code/Algorithms/mitkCoreObjectFactory.cpp +++ b/Core/Code/Algorithms/mitkCoreObjectFactory.cpp @@ -1,402 +1,400 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkConfig.h" #include "mitkCoreObjectFactory.h" #include "mitkAffineInteractor.h" #include "mitkColorProperty.h" #include "mitkDataNode.h" #include "mitkEnumerationProperty.h" #include "mitkGeometry2DData.h" #include "mitkGeometry2DDataMapper2D.h" #include "mitkGeometry2DDataVtkMapper3D.h" #include "mitkGeometry3D.h" #include "mitkGeometryData.h" #include "mitkImage.h" -#include "mitkImageMapperGL2D.h" +#include #include "mitkLevelWindowProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkPlaneGeometry.h" #include "mitkPointSet.h" #include "mitkPointSetGLMapper2D.h" #include "mitkPointSetVtkMapper3D.h" #include "mitkPolyDataGLMapper2D.h" #include "mitkProperties.h" #include "mitkPropertyList.h" #include "mitkSlicedGeometry3D.h" #include "mitkSmartPointerProperty.h" #include "mitkStringProperty.h" #include "mitkSurface.h" #include "mitkSurface.h" #include "mitkSurfaceGLMapper2D.h" #include "mitkSurfaceVtkMapper3D.h" #include "mitkTimeSlicedGeometry.h" #include "mitkTransferFunctionProperty.h" #include "mitkVolumeDataVtkMapper3D.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkPicFileIOFactory.h" #include "mitkPointSetIOFactory.h" #include "mitkItkImageFileIOFactory.h" #include "mitkSTLFileIOFactory.h" #include "mitkVtkSurfaceIOFactory.h" #include "mitkVtkImageIOFactory.h" #include "mitkVtiFileIOFactory.h" #include "mitkPicVolumeTimeSeriesIOFactory.h" #include "mitkImageWriterFactory.h" #include "mitkPointSetWriterFactory.h" #include "mitkSurfaceVtkWriterFactory.h" mitk::CoreObjectFactory::FileWriterList mitk::CoreObjectFactory::m_FileWriters; void mitk::CoreObjectFactory::RegisterExtraFactory(CoreObjectFactoryBase* factory) { MITK_INFO << "CoreObjectFactory: registering extra factory of type " << factory->GetNameOfClass(); m_ExtraFactories.insert(CoreObjectFactoryBase::Pointer(factory)); } void mitk::CoreObjectFactory::UnRegisterExtraFactory(CoreObjectFactoryBase *factory) { MITK_INFO << "CoreObjectFactory: un-registering extra factory of type " << factory->GetNameOfClass(); try { m_ExtraFactories.erase(factory); } catch( std::exception const& e) { MITK_ERROR << "Caugt exception while unregistering: " << e.what(); } } mitk::CoreObjectFactory::Pointer mitk::CoreObjectFactory::GetInstance() { static mitk::CoreObjectFactory::Pointer instance; if (instance.IsNull()) { instance = mitk::CoreObjectFactory::New(); } return instance; } #include void mitk::CoreObjectFactory::SetDefaultProperties(mitk::DataNode* node) { if(node==NULL) return; mitk::DataNode::Pointer nodePointer = node; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNotNull() && image->IsInitialized()) { - mitk::ImageMapperGL2D::SetDefaultProperties(node); + mitk::ImageVtkMapper2D::SetDefaultProperties(node); mitk::VolumeDataVtkMapper3D::SetDefaultProperties(node); } mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNotNull()) { mitk::SurfaceGLMapper2D::SetDefaultProperties(node); mitk::SurfaceVtkMapper3D::SetDefaultProperties(node); } mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData()); if(pointSet.IsNotNull()) { mitk::PointSetGLMapper2D::SetDefaultProperties(node); mitk::PointSetVtkMapper3D::SetDefaultProperties(node); } for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) { (*it)->SetDefaultProperties(node); } } mitk::CoreObjectFactory::CoreObjectFactory() { static bool alreadyDone = false; if (!alreadyDone) { MITK_INFO << "CoreObjectFactory c'tor" << std::endl; itk::ObjectFactoryBase::RegisterFactory( PicFileIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( PointSetIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( STLFileIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( VtkSurfaceIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( VtkImageIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( VtiFileIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( ItkImageFileIOFactory::New() ); itk::ObjectFactoryBase::RegisterFactory( PicVolumeTimeSeriesIOFactory::New() ); mitk::SurfaceVtkWriterFactory::RegisterOneFactory(); mitk::PointSetWriterFactory::RegisterOneFactory(); mitk::ImageWriterFactory::RegisterOneFactory(); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::Mapper::Pointer mitk::CoreObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper = NULL; mitk::Mapper::Pointer tmpMapper = NULL; // check whether extra factories provide mapper for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) { tmpMapper = (*it)->CreateMapper(node,id); if(tmpMapper.IsNotNull()) newMapper = tmpMapper; } if (newMapper.IsNull()) { mitk::BaseData *data = node->GetData(); if ( id == mitk::BaseRenderer::Standard2D ) { if((dynamic_cast(data)!=NULL)) { - mitk::Image::Pointer image = dynamic_cast(data); - newMapper = mitk::ImageMapperGL2D::New(); + newMapper = mitk::ImageVtkMapper2D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::Geometry2DDataMapper2D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::SurfaceGLMapper2D::New(); // cast because SetDataNode is not virtual mitk::SurfaceGLMapper2D *castedMapper = dynamic_cast(newMapper.GetPointer()); castedMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::PointSetGLMapper2D::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { if((dynamic_cast(data) != NULL)) { newMapper = mitk::VolumeDataVtkMapper3D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::Geometry2DDataVtkMapper3D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::SurfaceVtkMapper3D::New(); newMapper->SetDataNode(node); } else if((dynamic_cast(data)!=NULL)) { newMapper = mitk::PointSetVtkMapper3D::New(); - //newMapper = mitk::EnhancedPointSetVtkMapper3D::New(); // <-- use this if you want to try the new work in progres point set mapper newMapper->SetDataNode(node); } } } return newMapper; } /* // @deprecated // #define EXTERNAL_FILE_EXTENSIONS \ "All known formats(*.dcm *.DCM *.dc3 *.DC3 *.gdcm *.ima *.mhd *.mps *.nii *.pic *.pic.gz *.bmp *.png *.jpg *.tiff *.pvtk *.stl *.vtk *.vtp *.vtu *.obj *.vti *.hdr *.nrrd *.nhdr );;" \ "DICOM files(*.dcm *.DCM *.dc3 *.DC3 *.gdcm);;" \ "DKFZ Pic (*.seq *.pic *.pic.gz *.seq.gz);;" \ "NRRD Vector Images (*.nrrd *.nhdr);;" \ "Point sets (*.mps);;" \ "Sets of 2D slices (*.pic *.pic.gz *.bmp *.png *.dcm *.gdcm *.ima *.tiff);;" \ "Surface files (*.stl *.vtk *.vtp *.obj);;" \ "NIfTI format (*.nii)" #define SAVE_FILE_EXTENSIONS "all (*.pic *.mhd *.vtk *.vti *.hdr *.png *.tiff *.jpg *.hdr *.bmp *.dcm *.gipl *.nii *.nrrd *.nhdr *.spr *.lsm *.dwi *.hdwi *.qbi *.hqbi)" */ /** * @brief This method gets the supported (open) file extensions as string. This string is can then used by the QT QFileDialog widget. * @return The c-string that contains the file extensions * */ const char* mitk::CoreObjectFactory::GetFileExtensions() { MultimapType aMap; for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) { aMap = (*it)->GetFileExtensionsMap(); this->MergeFileExtensions(m_FileExtensionsMap, aMap); } this->CreateFileExtensions(m_FileExtensionsMap, m_FileExtensions); return m_FileExtensions.c_str(); } /** * @brief Merge the input map into the fileExtensionsMap. Duplicate entries are removed * @param fileExtensionsMap the existing map, it contains value pairs like ("*.dcm", "DICOM files"),("*.dc3", "DICOM files"). * This map is extented/merged with the values from the input map. * @param inputMap the input map, it contains value pairs like ("*.dcm", "DICOM files"),("*.dc3", "DICOM files") returned by * the extra factories. * */ void mitk::CoreObjectFactory::MergeFileExtensions(MultimapType& fileExtensionsMap, MultimapType inputMap) { bool duplicateFound = false; std::pair pairOfIter; for (MultimapType::iterator it = inputMap.begin(); it != inputMap.end(); ++it) { duplicateFound = false; pairOfIter = fileExtensionsMap.equal_range((*it).first); for (MultimapType::iterator it2 = pairOfIter.first; it2 != pairOfIter.second; ++it2) { //cout << " [" << (*it).first << ", " << (*it).second << "]" << endl; std::string aString = (*it2).second; if (aString.compare((*it).second) == 0) { //cout << " DUP!! [" << (*it).first << ", " << (*it).second << "]" << endl; duplicateFound = true; break; } } if (!duplicateFound) { fileExtensionsMap.insert(std::pair((*it).first, (*it).second)); } } } /** * @brief get the defined (open) file extension map * @return the defined (open) file extension map */ mitk::CoreObjectFactoryBase::MultimapType mitk::CoreObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } /** * @brief initialize the file extension entries for open and save */ void mitk::CoreObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.dcm", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.DCM", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.dc3", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.DC3", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.gdcm", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.seq", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.pic", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.pic.gz", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.mhd", "MetaImage")); m_FileExtensionsMap.insert(std::pair("*.seq.gz", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.nrrd", "Nearly Raw Raster Data")); m_FileExtensionsMap.insert(std::pair("*.nhdr", "NRRD Vector Images")); m_FileExtensionsMap.insert(std::pair("*.mps", "Point sets")); m_FileExtensionsMap.insert(std::pair("*.pic", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.pic.gz", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.bmp", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.png", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.jpg", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.jpeg", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.dcm", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.gdcm", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.ima", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.tiff", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.tif", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.stl", "Surface files")); m_FileExtensionsMap.insert(std::pair("*.vtk", "Surface files")); m_FileExtensionsMap.insert(std::pair("*.vtp", "Surface files")); m_FileExtensionsMap.insert(std::pair("*.obj", "Surface files")); m_FileExtensionsMap.insert(std::pair("*.nii", "NIfTI format")); //m_SaveFileExtensionsMap.insert(std::pair("*.pic", "DKFZ Pic")); m_SaveFileExtensionsMap.insert(std::pair("*.mhd", "MetaImage")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "Surface Files")); m_SaveFileExtensionsMap.insert(std::pair("*.vti", "VTK Image Data Files")); m_SaveFileExtensionsMap.insert(std::pair("*.hdr", "Image Header Files")); m_SaveFileExtensionsMap.insert(std::pair("*.png", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.tiff", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.tif", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.jpg", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.jpeg", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.bmp", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.dcm", "Sets of 2D slices")); m_SaveFileExtensionsMap.insert(std::pair("*.gipl", "UMDS GIPL Format Files")); m_SaveFileExtensionsMap.insert(std::pair("*.nii", "NIfTI format")); m_SaveFileExtensionsMap.insert(std::pair("*.nrrd", "Nearly Raw Raster Data")); m_SaveFileExtensionsMap.insert(std::pair("*.nhdr", "NRRD Vector Images")); m_SaveFileExtensionsMap.insert(std::pair("*.lsm", "Microscope Images")); m_SaveFileExtensionsMap.insert(std::pair("*.dwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hdwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.qbi", "Q-Ball Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hqbi", "Q-Ball Images")); } /** * @brief This method gets the supported (save) file extensions as string. This string is can then used by the QT QFileDialog widget. * @return The c-string that contains the (save) file extensions * */ const char* mitk::CoreObjectFactory::GetSaveFileExtensions() { MultimapType aMap; for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) { aMap = (*it)->GetSaveFileExtensionsMap(); this->MergeFileExtensions(m_SaveFileExtensionsMap, aMap); } this->CreateFileExtensions(m_SaveFileExtensionsMap, m_SaveFileExtensions); return m_SaveFileExtensions.c_str(); }; /** * @brief get the defined (save) file extension map * @return the defined (save) file extension map */ mitk::CoreObjectFactoryBase::MultimapType mitk::CoreObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } mitk::CoreObjectFactory::FileWriterList mitk::CoreObjectFactory::GetFileWriters() { FileWriterList allWriters = m_FileWriters; for (ExtraFactoriesContainer::iterator it = m_ExtraFactories.begin(); it != m_ExtraFactories.end() ; it++ ) { FileWriterList list2 = (*it)->GetFileWriters(); allWriters.merge(list2); } return allWriters; } void mitk::CoreObjectFactory::MapEvent(const mitk::Event*, const int) { } diff --git a/Core/Code/Controllers/mitkCameraController.cpp b/Core/Code/Controllers/mitkCameraController.cpp index c9aa71c183..3ddd05ac58 100644 --- a/Core/Code/Controllers/mitkCameraController.cpp +++ b/Core/Code/Controllers/mitkCameraController.cpp @@ -1,165 +1,170 @@ /*========================================================================= - + Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ - + Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. - + =========================================================================*/ #include "mitkCameraController.h" #include "mitkVtkPropRenderer.h" #include "mitkRenderingManager.h" #include #include "vtkCommand.h" #include "vtkCamera.h" #include "vtkRenderer.h" mitk::CameraController::CameraController(const char * type) : BaseController(type), m_Renderer(NULL), m_ZoomFactor(1.0) {} mitk::CameraController::~CameraController() {} void mitk::CameraController::Resize(int, int) {} void mitk::CameraController::MousePressEvent(mitk::MouseEvent*) {} void mitk::CameraController::MouseReleaseEvent(mitk::MouseEvent*) {} void mitk::CameraController::MouseMoveEvent(mitk::MouseEvent*) {} void mitk::CameraController::KeyPressEvent(mitk::KeyEvent*) {} void mitk::CameraController::SetViewToAnterior() { this->SetStandardView(ANTERIOR); } void mitk::CameraController::SetViewToPosterior() { this->SetStandardView(POSTERIOR); } void mitk::CameraController::SetViewToSinister() { this->SetStandardView(SINISTER); } void mitk::CameraController::SetViewToDexter() { this->SetStandardView(DEXTER); } void mitk::CameraController::SetViewToCranial() { this->SetStandardView(CRANIAL); } void mitk::CameraController::SetViewToCaudal() { this->SetStandardView(CAUDAL); } void mitk::CameraController::SetStandardView( mitk::CameraController::StandardView view ) { const mitk::VtkPropRenderer* glRenderer = dynamic_cast(m_Renderer); if (glRenderer == NULL) return; vtkRenderer* vtkRenderer = glRenderer->GetVtkRenderer(); assert (vtkRenderer); mitk::BoundingBox::Pointer bb; mitk::DataStorage* ds = m_Renderer->GetDataStorage(); if (ds != NULL) bb = ds->ComputeBoundingBox(); else return; - mitk::Point3D middle = bb->GetCenter(); - vtkRenderer->GetActiveCamera()->SetFocalPoint(middle[0], middle[1], middle[2]); - switch(view) - { - case ANTERIOR: - case POSTERIOR: - case SINISTER: - case DEXTER: - vtkRenderer->GetActiveCamera()->SetViewUp(0,0,1); - break; - case CRANIAL: - case CAUDAL: - vtkRenderer->GetActiveCamera()->SetViewUp(0,-1,0); - } - switch(view) - { - case ANTERIOR: - vtkRenderer->GetActiveCamera()->SetPosition(middle[0],-100000,middle[2]); - break; - case POSTERIOR: - vtkRenderer->GetActiveCamera()->SetPosition(middle[0],+100000,middle[2]); - break; - case SINISTER: - vtkRenderer->GetActiveCamera()->SetPosition(+100000,middle[1],middle[2]); - break; - case DEXTER: - vtkRenderer->GetActiveCamera()->SetPosition(-100000,middle[1],middle[2]); - break; - case CRANIAL: - vtkRenderer->GetActiveCamera()->SetPosition(middle[0],middle[1],100000); - break; - case CAUDAL: - vtkRenderer->GetActiveCamera()->SetPosition(middle[0],middle[1],-100000); - break; - } - vtkRenderer->ResetCamera(); - double *cameraPosition = vtkRenderer->GetActiveCamera()->GetPosition(); - switch(view) + if(m_Renderer->GetMapperID() == mitk::BaseRenderer::Standard3D) { - case ANTERIOR: - case POSTERIOR: - vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0],cameraPosition[1] / m_ZoomFactor,cameraPosition[2]); - break; - - case SINISTER: - case DEXTER: - vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0] / m_ZoomFactor,cameraPosition[1],cameraPosition[2]); - break; - - case CRANIAL: - case CAUDAL: - vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0],cameraPosition[1],cameraPosition[2] / m_ZoomFactor); - break; + //set up the view for the 3D render window. The views for 2D are set up in the mitkVtkPropRenderer + mitk::Point3D middle = bb->GetCenter(); + vtkRenderer->GetActiveCamera()->SetFocalPoint(middle[0], middle[1], middle[2]); + switch(view) + { + case ANTERIOR: + case POSTERIOR: + case SINISTER: + case DEXTER: + vtkRenderer->GetActiveCamera()->SetViewUp(0,0,1); + break; + case CRANIAL: + case CAUDAL: + vtkRenderer->GetActiveCamera()->SetViewUp(0,-1,0); + break; + } + switch(view) + { + case ANTERIOR: + vtkRenderer->GetActiveCamera()->SetPosition(middle[0],-100000,middle[2]); + break; + case POSTERIOR: + vtkRenderer->GetActiveCamera()->SetPosition(middle[0],+100000,middle[2]); + break; + case SINISTER: + vtkRenderer->GetActiveCamera()->SetPosition(+100000,middle[1],middle[2]); + break; + case DEXTER: + vtkRenderer->GetActiveCamera()->SetPosition(-100000,middle[1],middle[2]); + break; + case CRANIAL: + vtkRenderer->GetActiveCamera()->SetPosition(middle[0],middle[1],100000); + break; + case CAUDAL: + vtkRenderer->GetActiveCamera()->SetPosition(middle[0],middle[1],-100000); + break; + } + vtkRenderer->ResetCamera(); + double *cameraPosition = vtkRenderer->GetActiveCamera()->GetPosition(); + switch(view) + { + case ANTERIOR: + case POSTERIOR: + vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0],cameraPosition[1] / m_ZoomFactor,cameraPosition[2]); + break; + + case SINISTER: + case DEXTER: + vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0] / m_ZoomFactor,cameraPosition[1],cameraPosition[2]); + break; + + case CRANIAL: + case CAUDAL: + vtkRenderer->GetActiveCamera()->SetPosition(cameraPosition[0],cameraPosition[1],cameraPosition[2] / m_ZoomFactor); + break; + } + vtkRenderer->ResetCameraClippingRange(); } - vtkRenderer->ResetCameraClippingRange(); mitk::RenderingManager* rm = m_Renderer->GetRenderingManager(); rm->RequestUpdateAll(); } diff --git a/Core/Code/Controllers/mitkRenderingManager.cpp b/Core/Code/Controllers/mitkRenderingManager.cpp index a2d91fc9d1..c47da30e23 100644 --- a/Core/Code/Controllers/mitkRenderingManager.cpp +++ b/Core/Code/Controllers/mitkRenderingManager.cpp @@ -1,997 +1,1011 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkRenderingManager.h" #include "mitkRenderingManagerFactory.h" #include "mitkBaseRenderer.h" #include "mitkGlobalInteraction.h" #include #include #include "mitkVector.h" #include #include +#include #include namespace mitk { RenderingManager::Pointer RenderingManager::s_Instance = 0; RenderingManagerFactory *RenderingManager::s_RenderingManagerFactory = 0; RenderingManager ::RenderingManager() : m_UpdatePending( false ), m_MaxLOD( 1 ), m_LODIncreaseBlocked( false ), m_LODAbortMechanismEnabled( false ), m_ClippingPlaneEnabled( false ), m_TimeNavigationController( NULL ), m_ConstrainedPaddingZooming ( true ), m_DataStorage( NULL ) { m_ShadingEnabled.assign( 3, false ); m_ShadingValues.assign( 4, 0.0 ); m_GlobalInteraction = mitk::GlobalInteraction::GetInstance(); InitializePropertyList(); } RenderingManager ::~RenderingManager() { // Decrease reference counts of all registered vtkRenderWindows for // proper destruction RenderWindowVector::iterator it; for ( it = m_AllRenderWindows.begin(); it != m_AllRenderWindows.end(); ++it ) { (*it)->UnRegister( NULL ); RenderWindowCallbacksList::iterator callbacks_it = this->m_RenderWindowCallbacksList.find(*it); (*it)->RemoveObserver(callbacks_it->second.commands[0u]); (*it)->RemoveObserver(callbacks_it->second.commands[1u]); (*it)->RemoveObserver(callbacks_it->second.commands[2u]); } } void RenderingManager ::SetFactory( RenderingManagerFactory *factory ) { s_RenderingManagerFactory = factory; } const RenderingManagerFactory * RenderingManager ::GetFactory() { return s_RenderingManagerFactory; } bool RenderingManager ::HasFactory() { if ( RenderingManager::s_RenderingManagerFactory ) { return true; } else { return false; } } RenderingManager::Pointer RenderingManager ::New() { const RenderingManagerFactory* factory = GetFactory(); if(factory == NULL) return NULL; return factory->CreateRenderingManager(); } RenderingManager * RenderingManager ::GetInstance() { if ( !RenderingManager::s_Instance ) { if ( s_RenderingManagerFactory ) { s_Instance = s_RenderingManagerFactory->CreateRenderingManager(); } } return s_Instance; } bool RenderingManager ::IsInstantiated() { if ( RenderingManager::s_Instance ) return true; else return false; } void RenderingManager ::AddRenderWindow( vtkRenderWindow *renderWindow ) { if ( renderWindow && (m_RenderWindowList.find( renderWindow ) == m_RenderWindowList.end()) ) { m_RenderWindowList[renderWindow] = RENDERING_INACTIVE; m_AllRenderWindows.push_back( renderWindow ); if ( m_DataStorage.IsNotNull() ) mitk::BaseRenderer::GetInstance( renderWindow )->SetDataStorage( m_DataStorage.GetPointer() ); + // Register vtkRenderWindow instance renderWindow->Register( NULL ); typedef itk::MemberCommand< RenderingManager > MemberCommandType; // Add callbacks for rendering abort mechanism //BaseRenderer *renderer = BaseRenderer::GetInstance( renderWindow ); vtkCallbackCommand *startCallbackCommand = vtkCallbackCommand::New(); startCallbackCommand->SetCallback( RenderingManager::RenderingStartCallback ); renderWindow->AddObserver( vtkCommand::StartEvent, startCallbackCommand ); vtkCallbackCommand *progressCallbackCommand = vtkCallbackCommand::New(); progressCallbackCommand->SetCallback( RenderingManager::RenderingProgressCallback ); renderWindow->AddObserver( vtkCommand::AbortCheckEvent, progressCallbackCommand ); vtkCallbackCommand *endCallbackCommand = vtkCallbackCommand::New(); endCallbackCommand->SetCallback( RenderingManager::RenderingEndCallback ); renderWindow->AddObserver( vtkCommand::EndEvent, endCallbackCommand ); RenderWindowCallbacks callbacks; callbacks.commands[0u] = startCallbackCommand; callbacks.commands[1u] = progressCallbackCommand; callbacks.commands[2u] = endCallbackCommand; this->m_RenderWindowCallbacksList[renderWindow] = callbacks; //Delete vtk variables correctly startCallbackCommand->Delete(); progressCallbackCommand->Delete(); endCallbackCommand->Delete(); } } void RenderingManager ::RemoveRenderWindow( vtkRenderWindow *renderWindow ) { if (m_RenderWindowList.erase( renderWindow )) { RenderWindowCallbacksList::iterator callbacks_it = this->m_RenderWindowCallbacksList.find(renderWindow); renderWindow->RemoveObserver(callbacks_it->second.commands[0u]); renderWindow->RemoveObserver(callbacks_it->second.commands[1u]); renderWindow->RemoveObserver(callbacks_it->second.commands[2u]); this->m_RenderWindowCallbacksList.erase(callbacks_it); RenderWindowVector::iterator rw_it = std::find( m_AllRenderWindows.begin(), m_AllRenderWindows.end(), renderWindow ); // Decrease reference count for proper destruction (*rw_it)->UnRegister(NULL); m_AllRenderWindows.erase( rw_it ); } } const RenderingManager::RenderWindowVector& RenderingManager ::GetAllRegisteredRenderWindows() { return m_AllRenderWindows; } void RenderingManager ::RequestUpdate( vtkRenderWindow *renderWindow ) { m_RenderWindowList[renderWindow] = RENDERING_REQUESTED; if ( !m_UpdatePending ) { m_UpdatePending = true; this->GenerateRenderingRequestEvent(); } } void RenderingManager ::ForceImmediateUpdate( vtkRenderWindow *renderWindow ) { // Erase potentially pending requests for this window m_RenderWindowList[renderWindow] = RENDERING_INACTIVE; m_UpdatePending = false; // Immediately repaint this window (implementation platform specific) // If the size is 0 it crahses int *size = renderWindow->GetSize(); if ( 0 != size[0] && 0 != size[1] ) { + //prepare the camera etc. before rendering + //Note: this is a very important step which should be called before the VTK render! + //If you modify the camera anywhere else or after the render call, the scene cannot be seen. + mitk::VtkPropRenderer *vPR = + dynamic_cast(mitk::BaseRenderer::GetInstance( renderWindow )); + if(vPR) + vPR->PrepareRender(); // Execute rendering renderWindow->Render(); } } void RenderingManager ::RequestUpdateAll( RequestType type ) { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { int id = BaseRenderer::GetInstance(it->first)->GetMapperID(); if ( (type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)) ) { - this->RequestUpdate( it->first ); + this->RequestUpdate( it->first ); } } } void RenderingManager ::ForceImmediateUpdateAll( RequestType type ) { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { int id = BaseRenderer::GetInstance(it->first)->GetMapperID(); if ( (type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)) ) { - //it->second = RENDERING_INPROGRESS; - // Immediately repaint this window (implementation platform specific) // If the size is 0, it crashes int *size = it->first->GetSize(); if ( 0 != size[0] && 0 != size[1] ) { + //prepare the camera before rendering + //Note: this is a very important step which should be called before the VTK render! + //If you modify the camera anywhere else or after the render call, the scene cannot be seen. + mitk::VtkPropRenderer *vPR = + dynamic_cast(mitk::BaseRenderer::GetInstance( it->first )); + if(vPR) + vPR->PrepareRender(); // Execute rendering it->first->Render(); } it->second = RENDERING_INACTIVE; } } m_UpdatePending = false; } //bool RenderingManager::InitializeViews( const mitk::DataStorage * storage, const DataNode* node = NULL, RequestType type, bool preserveRoughOrientationInWorldSpace ) //{ // mitk::Geometry3D::Pointer geometry; // if ( storage != NULL ) // { // geometry = storage->ComputeVisibleBoundingGeometry3D(node, "visible", NULL, "includeInBoundingBox" ); // // if ( geometry.IsNotNull() ) // { // // let's see if we have data with a limited live-span ... // mitk::TimeBounds timebounds = geometry->GetTimeBounds(); // if ( timebounds[1] < mitk::ScalarTypeNumericTraits::max() ) // { // mitk::ScalarType duration = timebounds[1]-timebounds[0]; // // mitk::TimeSlicedGeometry::Pointer timegeometry = // mitk::TimeSlicedGeometry::New(); // timegeometry->InitializeEvenlyTimed( // geometry, (unsigned int) duration ); // timegeometry->SetTimeBounds( timebounds ); // // timebounds[1] = timebounds[0] + 1.0; // geometry->SetTimeBounds( timebounds ); // // geometry = timegeometry; // } // } // } // // // Use geometry for initialization // return this->InitializeViews( geometry.GetPointer(), type ); //} bool RenderingManager ::InitializeViews( const Geometry3D * dataGeometry, RequestType type, bool preserveRoughOrientationInWorldSpace ) { MITK_DEBUG << "initializing views"; bool boundingBoxInitialized = false; Geometry3D::ConstPointer geometry = dataGeometry; if (dataGeometry && preserveRoughOrientationInWorldSpace) { // clone the input geometry Geometry3D::Pointer modifiedGeometry = dynamic_cast( dataGeometry->Clone().GetPointer() ); assert(modifiedGeometry.IsNotNull()); // construct an affine transform from it AffineGeometryFrame3D::TransformType::Pointer transform = AffineGeometryFrame3D::TransformType::New(); assert( modifiedGeometry->GetIndexToWorldTransform() ); transform->SetMatrix( modifiedGeometry->GetIndexToWorldTransform()->GetMatrix() ); transform->SetOffset( modifiedGeometry->GetIndexToWorldTransform()->GetOffset() ); // get transform matrix AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType& oldMatrix = const_cast< AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType& > ( transform->GetMatrix().GetVnlMatrix() ); AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType newMatrix(oldMatrix); // get offset and bound Vector3D offset = modifiedGeometry->GetIndexToWorldTransform()->GetOffset(); Geometry3D::BoundsArrayType oldBounds = modifiedGeometry->GetBounds(); Geometry3D::BoundsArrayType newBounds = modifiedGeometry->GetBounds(); // get rid of rotation other than pi/2 degree for ( unsigned int i = 0; i < 3; ++i ) { // i-th column of the direction matrix Vector3D currentVector; currentVector[0] = oldMatrix(0,i); currentVector[1] = oldMatrix(1,i); currentVector[2] = oldMatrix(2,i); // matchingRow will store the row that holds the biggest // value in the column unsigned int matchingRow = 0; // maximum value in the column float max = std::numeric_limits::min(); // sign of the maximum value (-1 or 1) int sign = 1; // iterate through the column vector for (unsigned int dim = 0; dim < 3; ++dim) { if ( fabs(currentVector[dim]) > max ) { matchingRow = dim; max = fabs(currentVector[dim]); if(currentVector[dim]<0) sign = -1; else sign = 1; } } // in case we found a negative maximum, // we negate the column and adjust the offset // (in order to run through the dimension in the opposite direction) if(sign == -1) { currentVector *= sign; offset += modifiedGeometry->GetAxisVector(i); } // matchingRow is now used as column index to place currentVector // correctly in the new matrix vnl_vector newMatrixColumn(3); newMatrixColumn[0] = currentVector[0]; newMatrixColumn[1] = currentVector[1]; newMatrixColumn[2] = currentVector[2]; newMatrix.set_column( matchingRow, newMatrixColumn ); // if a column is moved, we also have to adjust the bounding // box accordingly, this is done here newBounds[2*matchingRow ] = oldBounds[2*i ]; newBounds[2*matchingRow+1] = oldBounds[2*i+1]; } // set the newly calculated bounds array modifiedGeometry->SetBounds(newBounds); // set new offset and direction matrix AffineGeometryFrame3D::TransformType::MatrixType newMatrixITK( newMatrix ); transform->SetMatrix( newMatrixITK ); transform->SetOffset( offset ); modifiedGeometry->SetIndexToWorldTransform( transform ); geometry = modifiedGeometry; } int warningLevel = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); if ( (geometry.IsNotNull() ) && (const_cast< mitk::BoundingBox * >( geometry->GetBoundingBox())->GetDiagonalLength2() > mitk::eps) ) { boundingBoxInitialized = true; } if (geometry.IsNotNull() ) {// make sure bounding box has an extent bigger than zero in any direction // clone the input geometry Geometry3D::Pointer modifiedGeometry = dynamic_cast( dataGeometry->Clone().GetPointer() ); assert(modifiedGeometry.IsNotNull()); Geometry3D::BoundsArrayType newBounds = modifiedGeometry->GetBounds(); for( unsigned int dimension = 0; ( 2 * dimension ) < newBounds.Size() ; dimension++ ) { //check for equality but for an epsilon if( Equal( newBounds[ 2 * dimension ], newBounds[ 2 * dimension + 1 ] ) ) { newBounds[ 2 * dimension + 1 ] += 1; } } // set the newly calculated bounds array modifiedGeometry->SetBounds(newBounds); geometry = modifiedGeometry; } RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( it->first ); baseRenderer->GetDisplayGeometry()->SetConstrainZoomingAndPanning(m_ConstrainedPaddingZooming); int id = baseRenderer->GetMapperID(); if ( ((type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2))) ) { this->InternalViewInitialization( baseRenderer, geometry, boundingBoxInitialized, id ); } } if ( m_TimeNavigationController != NULL ) { if ( boundingBoxInitialized ) { m_TimeNavigationController->SetInputWorldGeometry( geometry ); } m_TimeNavigationController->Update(); } this->RequestUpdateAll( type ); vtkObject::SetGlobalWarningDisplay( warningLevel ); // Inform listeners that views have been initialized this->InvokeEvent( mitk::RenderingManagerViewsInitializedEvent() ); return boundingBoxInitialized; } bool RenderingManager ::InitializeViews( RequestType type ) { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( it->first ); int id = baseRenderer->GetMapperID(); if ( (type == REQUEST_UPDATE_ALL) || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1)) || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)) ) { mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); // Update the SNC nc->Update(); } } this->RequestUpdateAll( type ); return true; } //bool RenderingManager::InitializeView( vtkRenderWindow * renderWindow, const DataStorage* ds, const DataNode node = NULL, bool initializeGlobalTimeSNC ) //{ // mitk::Geometry3D::Pointer geometry; // if ( ds != NULL ) // { // geometry = ds->ComputeVisibleBoundingGeometry3D(node, NULL, "includeInBoundingBox" ); // // if ( geometry.IsNotNull() ) // { // // let's see if we have data with a limited live-span ... // mitk::TimeBounds timebounds = geometry->GetTimeBounds(); // if ( timebounds[1] < mitk::ScalarTypeNumericTraits::max() ) // { // mitk::ScalarType duration = timebounds[1]-timebounds[0]; // // mitk::TimeSlicedGeometry::Pointer timegeometry = // mitk::TimeSlicedGeometry::New(); // timegeometry->InitializeEvenlyTimed( // geometry, (unsigned int) duration ); // timegeometry->SetTimeBounds( timebounds ); // // timebounds[1] = timebounds[0] + 1.0; // geometry->SetTimeBounds( timebounds ); // // geometry = timegeometry; // } // } // } // // // Use geometry for initialization // return this->InitializeView( renderWindow, // geometry.GetPointer(), initializeGlobalTimeSNC ); //} bool RenderingManager::InitializeView( vtkRenderWindow * renderWindow, const Geometry3D * geometry, bool initializeGlobalTimeSNC ) { bool boundingBoxInitialized = false; int warningLevel = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); if ( (geometry != NULL ) && (const_cast< mitk::BoundingBox * >( geometry->GetBoundingBox())->GetDiagonalLength2() > mitk::eps) ) { boundingBoxInitialized = true; } mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( renderWindow ); int id = baseRenderer->GetMapperID(); this->InternalViewInitialization( baseRenderer, geometry, boundingBoxInitialized, id ); if ( m_TimeNavigationController != NULL ) { if ( boundingBoxInitialized && initializeGlobalTimeSNC ) { m_TimeNavigationController->SetInputWorldGeometry( geometry ); } m_TimeNavigationController->Update(); } this->RequestUpdate( renderWindow ); vtkObject::SetGlobalWarningDisplay( warningLevel ); return boundingBoxInitialized; } bool RenderingManager::InitializeView( vtkRenderWindow * renderWindow ) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( renderWindow ); mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); // Update the SNC nc->Update(); this->RequestUpdate( renderWindow ); return true; } void RenderingManager::InternalViewInitialization(mitk::BaseRenderer *baseRenderer, const mitk::Geometry3D *geometry, bool boundingBoxInitialized, int mapperID ) { mitk::SliceNavigationController *nc = baseRenderer->GetSliceNavigationController(); // Re-initialize view direction nc->SetViewDirectionToDefault(); if ( boundingBoxInitialized ) { // Set geometry for NC nc->SetInputWorldGeometry( geometry ); nc->Update(); if ( mapperID == 1 ) { // For 2D SNCs, steppers are set so that the cross is centered // in the image nc->GetSlice()->SetPos( nc->GetSlice()->GetSteps() / 2 ); } // Fit the render window DisplayGeometry baseRenderer->GetDisplayGeometry()->Fit(); baseRenderer->GetCameraController()->SetViewToAnterior(); } else { nc->Update(); } } void RenderingManager::SetTimeNavigationController( SliceNavigationController *nc ) { m_TimeNavigationController = nc; } const SliceNavigationController* RenderingManager::GetTimeNavigationController() const { return m_TimeNavigationController; } SliceNavigationController* RenderingManager::GetTimeNavigationController() { return m_TimeNavigationController; } void RenderingManager::ExecutePendingRequests() { m_UpdatePending = false; // Satisfy all pending update requests RenderWindowList::iterator it; int i = 0; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it, ++i ) { if ( it->second == RENDERING_REQUESTED ) { this->ForceImmediateUpdate( it->first ); } } } void RenderingManager::RenderingStartCallback( vtkObject *caller, unsigned long , void *, void * ) { vtkRenderWindow *renderWindow = dynamic_cast< vtkRenderWindow * >( caller ); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); RenderWindowList &renderWindowList = renman->m_RenderWindowList; if ( renderWindow ) { renderWindowList[renderWindow] = RENDERING_INPROGRESS; } renman->m_UpdatePending = false; } void RenderingManager ::RenderingProgressCallback( vtkObject *caller, unsigned long , void *, void * ) { vtkRenderWindow *renderWindow = dynamic_cast< vtkRenderWindow * >( caller ); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); if ( renman->m_LODAbortMechanismEnabled ) { vtkRenderWindow *renderWindow = dynamic_cast< vtkRenderWindow * >( caller ); if ( renderWindow ) { BaseRenderer *renderer = BaseRenderer::GetInstance( renderWindow ); if ( renderer && (renderer->GetNumberOfVisibleLODEnabledMappers() > 0) ) { renman->DoMonitorRendering(); } } } } void RenderingManager ::RenderingEndCallback( vtkObject *caller, unsigned long , void *, void * ) { vtkRenderWindow *renderWindow = dynamic_cast< vtkRenderWindow * >( caller ); mitk::RenderingManager* renman = mitk::BaseRenderer::GetInstance(renderWindow)->GetRenderingManager(); RenderWindowList &renderWindowList = renman->m_RenderWindowList; RendererIntMap &nextLODMap = renman->m_NextLODMap; if ( renderWindow ) { BaseRenderer *renderer = BaseRenderer::GetInstance( renderWindow ); if ( renderer ) { renderWindowList[renderer->GetRenderWindow()] = RENDERING_INACTIVE; // Level-of-Detail handling if ( renderer->GetNumberOfVisibleLODEnabledMappers() > 0 ) { if(nextLODMap[renderer]==0) renman->StartOrResetTimer(); else nextLODMap[renderer] = 0; } } } } bool RenderingManager ::IsRendering() const { RenderWindowList::const_iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { if ( it->second == RENDERING_INPROGRESS ) { return true; } } return false; } void RenderingManager ::AbortRendering() { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { if ( it->second == RENDERING_INPROGRESS ) { it->first->SetAbortRender( true ); m_RenderingAbortedMap[BaseRenderer::GetInstance(it->first)] = true; } } } int RenderingManager ::GetNextLOD( BaseRenderer *renderer ) { if ( renderer != NULL ) { return m_NextLODMap[renderer]; } else { return 0; } } void RenderingManager ::ExecutePendingHighResRenderingRequest() { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { BaseRenderer *renderer = BaseRenderer::GetInstance( it->first ); if(renderer->GetNumberOfVisibleLODEnabledMappers()>0) { if(m_NextLODMap[renderer]==0) { m_NextLODMap[renderer]=1; RequestUpdate( it->first ); } } } } void RenderingManager ::SetMaximumLOD( unsigned int max ) { m_MaxLOD = max; } //enable/disable shading void RenderingManager ::SetShading(bool state, unsigned int lod) { if(lod>m_MaxLOD) { itkWarningMacro(<<"LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD); return; } m_ShadingEnabled[lod] = state; } bool RenderingManager ::GetShading(unsigned int lod) { if(lod>m_MaxLOD) { itkWarningMacro(<<"LOD out of range requested: " << lod << " maxLOD: " << m_MaxLOD); return false; } return m_ShadingEnabled[lod]; } //enable/disable the clipping plane void RenderingManager ::SetClippingPlaneStatus(bool status) { m_ClippingPlaneEnabled = status; } bool RenderingManager ::GetClippingPlaneStatus() { return m_ClippingPlaneEnabled; } void RenderingManager ::SetShadingValues(float ambient, float diffuse, float specular, float specpower) { m_ShadingValues[0] = ambient; m_ShadingValues[1] = diffuse; m_ShadingValues[2] = specular; m_ShadingValues[3] = specpower; } RenderingManager::FloatVector & RenderingManager ::GetShadingValues() { return m_ShadingValues; } void RenderingManager::SetDepthPeelingEnabled( bool enabled ) { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( it->first ); baseRenderer->SetDepthPeelingEnabled(enabled); } } void RenderingManager::SetMaxNumberOfPeels( int maxNumber ) { RenderWindowList::iterator it; for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it ) { mitk::BaseRenderer *baseRenderer = mitk::BaseRenderer::GetInstance( it->first ); baseRenderer->SetMaxNumberOfPeels(maxNumber); } } void RenderingManager::InitializePropertyList() { if (m_PropertyList.IsNull()) { m_PropertyList = PropertyList::New(); } this->SetProperty("coupled-zoom", BoolProperty::New(false)); this->SetProperty("coupled-plane-rotation", BoolProperty::New(false)); this->SetProperty("MIP-slice-rendering", BoolProperty::New(false)); } PropertyList::Pointer RenderingManager::GetPropertyList() const { return m_PropertyList; } BaseProperty* RenderingManager::GetProperty(const char *propertyKey) const { return m_PropertyList->GetProperty(propertyKey); } void RenderingManager::SetProperty(const char *propertyKey, BaseProperty* propertyValue) { m_PropertyList->SetProperty(propertyKey, propertyValue); } void RenderingManager::SetDataStorage( DataStorage* storage ) { if ( storage != NULL ) { m_DataStorage = storage; RenderingManager::RenderWindowVector::iterator iter; for ( iter = m_AllRenderWindows.begin(); iterSetDataStorage( m_DataStorage.GetPointer() ); } } } mitk::DataStorage* RenderingManager::GetDataStorage() { return m_DataStorage; } void RenderingManager::SetGlobalInteraction( mitk::GlobalInteraction* globalInteraction ) { if ( globalInteraction != NULL ) { m_GlobalInteraction = globalInteraction; } } mitk::GlobalInteraction* RenderingManager::GetGlobalInteraction() { return m_GlobalInteraction; } // Create and register generic RenderingManagerFactory. TestingRenderingManagerFactory renderingManagerFactory; } // namespace diff --git a/Core/Code/Rendering/mitkBaseRenderer.h b/Core/Code/Rendering/mitkBaseRenderer.h index d51a2a4f9b..3a3749ce04 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.h +++ b/Core/Code/Rendering/mitkBaseRenderer.h @@ -1,585 +1,587 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #include "mitkDataStorage.h" #include "mitkGeometry2D.h" #include "mitkTimeSlicedGeometry.h" #include "mitkDisplayGeometry.h" #include "mitkGeometry2DData.h" #include "mitkCameraController.h" #include "mitkDisplayPositionEvent.h" #include "mitkWheelEvent.h" //#include "mitkMapper.h" #include "mitkSliceNavigationController.h" #include "mitkCameraController.h" #include "mitkCameraRotationController.h" #include #include #include #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; //##Documentation //## @brief Organizes the rendering process //## //## Organizes the rendering process. A Renderer contains a reference to a //## DataStorage and asks the mappers of the data objects to render //## the data into the renderwindow it is associated to. //## //## \#Render() checks if rendering is currently allowed by calling //## RenderWindow::PrepareRendering(). Initialization of a rendering context //## can also be performed in this method. //## //## The actual rendering code has been moved to \#Repaint() //## Both \#Repaint() and \#Update() are declared protected now. //## //## Note: Separation of the Repaint and Update processes (rendering vs //## creating a vtk prop tree) still needs to be worked on. The whole //## rendering process also should be reworked to use VTK based classes for //## both 2D and 3D rendering. //## @ingroup Renderer class MITK_CORE_EXPORT BaseRenderer : public itk::Object { public: typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; static BaseRenderer* GetInstance(vtkRenderWindow * renWin); static void AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer); static void RemoveInstance(vtkRenderWindow* renWin); static BaseRenderer* GetByName( const std::string& name ); static vtkRenderWindow* GetRenderWindowByName( const std::string& name ); #pragma GCC visibility push(default) itkEventMacro( RendererResetEvent, itk::AnyEvent ); #pragma GCC visibility pop /** Standard class typedefs. */ mitkClassMacro(BaseRenderer, itk::Object); BaseRenderer( const char* name = NULL, vtkRenderWindow * renWin = NULL, mitk::RenderingManager* rm= NULL ); //##Documentation //## @brief MapperSlotId defines which kind of mapper (e.g., 2D or 3D) shoud be used. typedef int MapperSlotId; enum StandardMapperSlot{Standard2D=1, Standard3D=2}; virtual void SetDataStorage( DataStorage* storage ); ///< set the datastorage that will be used for rendering //##Documentation //## return the DataStorage that is used for rendering virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); }; //##Documentation //## @brief Access the RenderWindow into which this renderer renders. vtkRenderWindow* GetRenderWindow() const { return m_RenderWindow; } vtkRenderer* GetVtkRenderer() const { return m_VtkRenderer; } //##Documentation //## @brief Default mapper id to use. static const MapperSlotId defaultMapper; //##Documentation //## @brief Do the rendering and flush the result. virtual void Paint(); //##Documentation //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. virtual void Initialize(); //##Documentation //## @brief Called to inform the renderer that the RenderWindow has been resized. virtual void Resize(int w, int h); //##Documentation //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). virtual void InitRenderer(vtkRenderWindow* renderwindow); //##Documentation //## @brief Set the initial size. Called by RenderWindow after it has become //## visible for the first time. virtual void InitSize(int w, int h); //##Documentation //## @brief Draws a point on the widget. //## Should be used during conferences to show the position of the remote mouse virtual void DrawOverlayMouse(Point2D& p2d); //##Documentation //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the //## (maximal) area to be rendered. //## //## Depending of the type of the passed Geometry3D more or less information can be extracted: //## \li if it is a Geometry2D (which is a sub-class of Geometry3D), m_CurrentWorldGeometry2D is //## also set to point to it. m_TimeSlicedWorldGeometry is set to NULL. //## \li if it is a TimeSlicedGeometry, m_TimeSlicedWorldGeometry is also set to point to it. //## If m_TimeSlicedWorldGeometry contains instances of SlicedGeometry3D, m_CurrentWorldGeometry2D is set to //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise //## a PlaneGeometry describing the top of the bounding-box of the Geometry3D is set as the //## m_CurrentWorldGeometry2D. //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the Geometry3D //## is set as the m_CurrentWorldGeometry2D. m_TimeSlicedWorldGeometry is set to NULL. //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the Geometry3D //## when the passed Geometry3D is not sliced. //## \sa m_WorldGeometry //## \sa m_TimeSlicedWorldGeometry //## \sa m_CurrentWorldGeometry2D virtual void SetWorldGeometry(Geometry3D* geometry); itkGetConstObjectMacro(WorldGeometry, Geometry3D); //##Documentation //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering itkGetConstObjectMacro(CurrentWorldGeometry, Geometry3D); //##Documentation //## @brief Get the current 2D-worldgeometry (m_CurrentWorldGeometry2D) used for 2D-rendering itkGetConstObjectMacro(CurrentWorldGeometry2D, Geometry2D); //##Documentation //## Calculates the bounds of the DataStorage (if it contains any valid data), //## creates a geometry from these bounds and sets it as world geometry of the renderer. //## //## Call this method to re-initialize the renderer to the current DataStorage //## (e.g. after loading an additional dataset), to ensure that the view is //## aligned correctly. //## \warn This is not implemented yet. virtual bool SetWorldGeometryToDataStorageBounds() { return false; } //##Documentation //## @brief Set/Get the DisplayGeometry (for 2D rendering) //## //## The DisplayGeometry describes which part of the Geometry2D m_CurrentWorldGeometry2D //## is displayed. virtual void SetDisplayGeometry(DisplayGeometry* geometry2d); itkGetConstObjectMacro(DisplayGeometry, DisplayGeometry); itkGetObjectMacro(DisplayGeometry, DisplayGeometry); //##Documentation //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_Slice virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int); //##Documentation //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_TimeStep virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int); //##Documentation //## @brief Get the time-step of a BaseData object which //## exists at the time of the currently displayed content //## //## Returns -1 or mitk::BaseData::m_TimeSteps if there //## is no data at the current time. //## \sa GetTimeStep, m_TimeStep int GetTimeStep(const BaseData* data) const; //##Documentation //## @brief Get the time in ms of the currently displayed content //## //## \sa GetTimeStep, m_TimeStep ScalarType GetTime() const; //##Documentation //## @brief SetWorldGeometry is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySendEvent virtual void SetGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the //## slice navigation controller virtual void UpdateGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetSlice is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySliceEvent virtual void SetGeometrySlice(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetTimeStep is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometryTimeEvent virtual void SetGeometryTime(const itk::EventObject & geometryTimeEvent); //##Documentation //## @brief Get a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryData, Geometry2DData); //##Documentation //## @brief Get a data object containing the WorldGeometry (for 2D rendering) itkGetObjectMacro(WorldGeometryData, Geometry2DData); //##Documentation //## @brief Get a DataNode pointing to a data object containing the WorldGeometry (3D and 2D rendering) itkGetObjectMacro(WorldGeometryNode, DataNode); //##Documentation //## @brief Get a DataNode pointing to a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryNode, DataNode); //##Documentation //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry m_CurrentWorldGeometry2D (for 2D rendering) itkGetObjectMacro(CurrentWorldGeometry2DNode, DataNode); //##Documentation //## @brief Sets timestamp of CurrentWorldGeometry2D and DisplayGeometry and forces so reslicing in that renderwindow void SendUpdateSlice(); //##Documentation //## @brief Get timestamp of last call of SetCurrentWorldGeometry2D unsigned long GetCurrentWorldGeometry2DUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; }; //##Documentation //## @brief Get timestamp of last call of SetDisplayGeometry unsigned long GetDisplayGeometryUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; }; //##Documentation //## @brief Get timestamp of last change of current TimeStep unsigned long GetTimeStepUpdateTime() { return m_TimeStepUpdateTime; }; //##Documentation //## @brief Perform a picking: find the x,y,z world coordinate of a //## display x,y coordinate. //## @warning Has to be overwritten in subclasses for the 3D-case. //## //## Implemented here only for 2D-rendering by using //## m_DisplayGeometry virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const; /** \brief Determines the object (mitk::DataNode) closest to the current * position by means of picking * * \warning Implementation currently empty for 2D rendering; intended to be * implemented for 3D renderers */ virtual DataNode* PickObject( const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/ ) const { return NULL; }; //##Documentation //## @brief Get the MapperSlotId to use. itkGetMacro(MapperID, MapperSlotId); + itkGetConstMacro(MapperID, MapperSlotId); + //##Documentation //## @brief Set the MapperSlotId to use. itkSetMacro(MapperID, MapperSlotId); //##Documentation //## @brief Has the renderer the focus? itkGetMacro(Focused, bool); //##Documentation //## @brief Tell the renderer that it is focused. The caller is responsible for focus management, //## not the renderer itself. itkSetMacro(Focused, bool); //##Documentation //## @brief Sets whether depth peeling is enabled or not void SetDepthPeelingEnabled(bool enabled); //##Documentation //## @brief Sets maximal number of peels void SetMaxNumberOfPeels(int maxNumber); itkGetMacro(Size, int*); void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); void SetCameraController(CameraController* cameraController); itkGetObjectMacro(CameraController, CameraController); itkGetObjectMacro(SliceNavigationController, SliceNavigationController); itkGetObjectMacro(CameraRotationController, CameraRotationController); itkGetMacro(EmptyWorldGeometry, bool); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MousePressEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseReleaseEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseMoveEvent(MouseEvent*); //##Documentation //## @brief Wheel event dispatcher //## @note for internal use only. preliminary. virtual void WheelEvent(mitk::WheelEvent* we); //##Documentation //## @brief Key event dispatcher //## @note for internal use only. preliminary. virtual void KeyPressEvent(KeyEvent*); //##Documentation //## @brief get the name of the Renderer //## @note const char * GetName() const { return m_Name.c_str(); } //##Documentation //## @brief get the x_size of the RendererWindow //## @note int GetSizeX() const { return m_Size[0]; } //##Documentation //## @brief get the y_size of the RendererWindow //## @note int GetSizeY() const { return m_Size[1]; } const double* GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); /** Returns number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; ///** //* \brief Setter for the RenderingManager that handles this instance of BaseRenderer //*/ //void SetRenderingManager( mitk::RenderingManager* ); /** * \brief Getter for the RenderingManager that handles this instance of BaseRenderer */ virtual mitk::RenderingManager* GetRenderingManager() const; protected: virtual ~BaseRenderer(); //##Documentation //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; vtkRenderWindow* m_RenderWindow; vtkRenderer* m_VtkRenderer; //##Documentation //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; //##Documentation //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; //##Documentation //## @brief The RenderingManager that manages this instance RenderingManager::Pointer m_RenderingManager; //##Documentation //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; //##Documentation //## @brief CameraController for 3D rendering //## @note preliminary. CameraController::Pointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; //##Documentation //## @brief Size of the RenderWindow. int m_Size[2]; //##Documentation //## @brief Contains whether the renderer that it is focused. The caller of //## SetFocused is responsible for focus management, not the renderer itself. //## is doubled because of mitk::FocusManager in GlobalInteraction!!! (ingmar) bool m_Focused; //##Documentation //## @brief Sets m_CurrentWorldGeometry2D virtual void SetCurrentWorldGeometry2D(Geometry2D* geometry2d); //##Documentation //## @brief Sets m_CurrentWorldGeometry virtual void SetCurrentWorldGeometry(Geometry3D* geometry); private: //##Documentation //## Pointer to the worldgeometry, describing the maximal area to be rendered //## (3D as well as 2D). //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). //## \sa SetWorldGeometry Geometry3D::Pointer m_WorldGeometry; //##Documentation //## m_TimeSlicedWorldGeometry is set by SetWorldGeometry if the passed Geometry3D is a //## TimeSlicedGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define //## which 2D geometry stored in m_TimeSlicedWorldGeometry (if available) //## is used as m_CurrentWorldGeometry2D. //## \sa m_CurrentWorldGeometry2D TimeSlicedGeometry::Pointer m_TimeSlicedWorldGeometry; //##Documentation //## Pointer to the current 3D-worldgeometry. Geometry3D::Pointer m_CurrentWorldGeometry; //##Documentation //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry //## describes the maximal area (2D manifold) to be rendered in case we //## are doing 2D-rendering. More precisely, a subpart of this according //## to m_DisplayGeometry is displayed. //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). Geometry2D::Pointer m_CurrentWorldGeometry2D; //##Documentation //## Pointer to the displaygeometry. The displaygeometry describes the //## geometry of the \em visible area in the window controlled by the renderer //## in case we are doing 2D-rendering. //## It is const, since we are not allowed to change it. DisplayGeometry::Pointer m_DisplayGeometry; //##Documentation //## Defines together with m_Slice which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_Slice; //##Documentation //## Defines together with m_TimeStep which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_TimeStep; //##Documentation //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldGeometry2DUpdateTime; //##Documentation //## @brief timestamp of last call of SetDisplayGeometry itk::TimeStamp m_DisplayGeometryUpdateTime; //##Documentation //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; protected: virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; //##Documentation //## Data object containing the m_WorldGeometry defined above. Geometry2DData::Pointer m_WorldGeometryData; //##Documentation //## Data object containing the m_DisplayGeometry defined above. Geometry2DData::Pointer m_DisplayGeometryData; //##Documentation //## Data object containing the m_CurrentWorldGeometry2D defined above. Geometry2DData::Pointer m_CurrentWorldGeometry2DData; //##Documentation //## DataNode objects containing the m_WorldGeometryData defined above. DataNode::Pointer m_WorldGeometryNode; //##Documentation //## DataNode objects containing the m_DisplayGeometryData defined above. DataNode::Pointer m_DisplayGeometryNode; //##Documentation //## DataNode objects containing the m_CurrentWorldGeometry2DData defined above. DataNode::Pointer m_CurrentWorldGeometry2DNode; //##Documentation //## @brief test only unsigned long m_DisplayGeometryTransformTime; //##Documentation //## @brief test only unsigned long m_CurrentWorldGeometry2DTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; bool m_DepthPeelingEnabled; int m_MaxNumberOfPeels; typedef std::set< Mapper * > LODEnabledMappersType; /** Number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; // Local Storage Handling for mappers protected: std::list m_RegisteredLocalStorageHandlers; public: void RemoveAllLocalStorages(); void RegisterLocalStorageHandler( mitk::BaseLocalStorageHandler *lsh ); void UnregisterLocalStorageHandler( mitk::BaseLocalStorageHandler *lsh ); }; } // namespace mitk #endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */ diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp index 9af4725ce6..e6de21c3fc 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp @@ -1,446 +1,452 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkGL.h" #include "mitkGeometry2DDataMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkSmartPointerProperty.h" #include "mitkPlaneOrientationProperty.h" #include "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkSurfaceGLMapper2D.h" #include "mitkLine.h" #include "mitkNodePredicateDataType.h" mitk::Geometry2DDataMapper2D::Geometry2DDataMapper2D() : m_SurfaceMapper( NULL ), m_DataStorage(NULL), m_ParentNode(NULL), m_OtherGeometry2Ds(), m_RenderOrientationArrows( false ), m_ArrowOrientationPositive( true ) { } mitk::Geometry2DDataMapper2D::~Geometry2DDataMapper2D() { } const mitk::Geometry2DData* mitk::Geometry2DDataMapper2D::GetInput(void) { return static_cast ( GetData() ); } void mitk::Geometry2DDataMapper2D::GenerateData() { // collect all Geometry2DDatas accessible from the DataStorage m_OtherGeometry2Ds.clear(); if (m_DataStorage.IsNull()) return; mitk::NodePredicateDataType::Pointer p = mitk::NodePredicateDataType::New("Geometry2DData"); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetDerivations(m_ParentNode, p, false); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { if(it->Value().IsNull()) continue; BaseData* data = it->Value()->GetData(); if (data == NULL) continue; Geometry2DData* geometry2dData = dynamic_cast(data); if(geometry2dData == NULL) continue; PlaneGeometry* planegeometry = dynamic_cast(geometry2dData->GetGeometry2D()); if (planegeometry != NULL) m_OtherGeometry2Ds.push_back(it->Value()); } } void mitk::Geometry2DDataMapper2D::Paint(BaseRenderer *renderer) { if ( !this->IsVisible(renderer) ) { return; } Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput()); // intersecting with ourself? if ( input.IsNull() || (this->GetInput()->GetGeometry2D() == renderer->GetCurrentWorldGeometry2D()) ) { return; // do nothing! } const PlaneGeometry *inputPlaneGeometry = dynamic_cast< const PlaneGeometry * >( input->GetGeometry2D() ); const PlaneGeometry *worldPlaneGeometry = dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldGeometry2D() ); if ( worldPlaneGeometry && inputPlaneGeometry && inputPlaneGeometry->GetReferenceGeometry() ) { DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry ); const Geometry3D *referenceGeometry = inputPlaneGeometry->GetReferenceGeometry(); // calculate intersection of the plane data with the border of the // world geometry rectangle Point2D lineFrom, lineTo; typedef Geometry3D::TransformType TransformType; const TransformType *transform = dynamic_cast< const TransformType * >( referenceGeometry->GetIndexToWorldTransform() ); TransformType::Pointer inverseTransform = TransformType::New(); transform->GetInverse( inverseTransform ); Line3D crossLine, otherCrossLine; // Calculate the intersection line of the input plane with the world plane if ( worldPlaneGeometry->IntersectionLine( inputPlaneGeometry, crossLine ) ) { BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if(referenceGeometry->GetImageGeometry()) { for(unsigned int i = 0; i < 3; ++i) { boundingBoxMin[i]-=0.5; boundingBoxMax[i]-=0.5; } } crossLine.Transform( *inverseTransform ); Point3D point1, point2; // Then, clip this line with the (transformed) bounding box of the // reference geometry. if ( crossLine.BoxLineIntersection( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2], boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2], crossLine.GetPoint(), crossLine.GetDirection(), point1, point2 ) == 2 ) { // Transform the resulting line start and end points into display // coordinates. worldPlaneGeometry->Map( transform->TransformPoint( point1 ), lineFrom ); worldPlaneGeometry->Map( transform->TransformPoint( point2 ), lineTo ); Line< ScalarType, 2 > line, otherLine; line.SetPoints( lineFrom, lineTo ); displayGeometry->WorldToDisplay( lineFrom, lineFrom ); displayGeometry->WorldToDisplay( lineTo, lineTo ); ScalarType lengthInDisplayUnits = (lineTo - lineFrom).GetNorm(); // lineParams stores the individual segments of the line, which are // separated by a gap each (to mark the intersection with another // displayed line) std::vector< ScalarType > lineParams; lineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); lineParams.push_back( 0.0 ); lineParams.push_back( 1.0 ); Vector2D d, dOrth; // Now iterate through all other lines displayed in this window and // calculate the positions of intersection with the line to be // rendered; these positions will be stored in lineParams to form a // gap afterwards. NodesVectorType::iterator otherPlanesIt = m_OtherGeometry2Ds.begin(); NodesVectorType::iterator otherPlanesEnd = m_OtherGeometry2Ds.end(); while ( otherPlanesIt != otherPlanesEnd ) { PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >( static_cast< Geometry2DData * >( (*otherPlanesIt)->GetData() )->GetGeometry2D() ); // Just as with the original line, calculate the intersaction with // the world geometry... if ( (otherPlane != inputPlaneGeometry) && worldPlaneGeometry->IntersectionLine( otherPlane, otherCrossLine ) ) { // ... and clip the resulting line segment with the reference // geometry bounding box. otherCrossLine.Transform( *inverseTransform ); if ( otherCrossLine.BoxLineIntersection( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2], boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2], otherCrossLine.GetPoint(), otherCrossLine.GetDirection(), point1, point2 ) == 2 ) { worldPlaneGeometry->Map( transform->TransformPoint( point1 ), lineFrom ); worldPlaneGeometry->Map( transform->TransformPoint( point2 ), lineTo ); // By means of the dot product, calculate the gap position as // parametric value in the range [0, 1] otherLine.SetPoints( lineFrom, lineTo ); d = otherLine.GetDirection(); dOrth[0] = -d[1]; dOrth[1] = d[0]; ScalarType t, norm; t = ( otherLine.GetPoint1() - line.GetPoint1() ) * dOrth; norm = line.GetDirection() * dOrth; if ( fabs( norm ) > eps ) { t /= norm; if ( (t > 0.0) && (t < 1.0) ) { lineParams.push_back(t); } } } } ++otherPlanesIt; } // Apply color and opacity read from the PropertyList. this->ApplyProperties( renderer ); ScalarType gapSizeInPixel = 10.0; ScalarType gapSizeInParamUnits = 1.0 / lengthInDisplayUnits * gapSizeInPixel; std::sort( lineParams.begin(), lineParams.end() ); Point2D p1, p2; ScalarType p1Param, p2Param; p1Param = lineParams[0]; p1 = line.GetPoint( p1Param ); displayGeometry->WorldToDisplay( p1, p1 ); + //Work arround to show the crosshair always on top of a 2D render window + //The image is usually located at depth = 0 or negative depth values, and thus, + //the crosshair with depth = 1 is always on top. + float depthPosition = 1.0f; + // Iterate over all line segments and display each, with a gap // inbetween. unsigned int i, preLastLineParam = lineParams.size() - 1; for ( i = 1; i < preLastLineParam; ++i ) { p2Param = lineParams[i] - gapSizeInParamUnits * 0.5; p2 = line.GetPoint( p2Param ); if ( p2Param > p1Param ) { // Convert intersection points (until now mm) to display // coordinates (units). displayGeometry->WorldToDisplay( p2, p2 ); // draw + glEnable(GL_DEPTH_TEST); glBegin (GL_LINES); - glVertex2f(p1[0],p1[1]); - glVertex2f(p2[0],p2[1]); + glVertex3f(p1[0],p1[1], depthPosition); + glVertex3f(p2[0],p2[1], depthPosition); glEnd (); if ( (i == 1) && (m_RenderOrientationArrows) ) { // Draw orientation arrow for first line segment this->DrawOrientationArrow( p1, p2, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); } } p1Param = p2Param + gapSizeInParamUnits; p1 = line.GetPoint( p1Param ); displayGeometry->WorldToDisplay( p1, p1 ); } // Draw last line segment p2Param = lineParams[i]; p2 = line.GetPoint( p2Param ); displayGeometry->WorldToDisplay( p2, p2 ); glBegin( GL_LINES ); - glVertex2f( p1[0], p1[1] ); - glVertex2f( p2[0], p2[1] ); + glVertex3f( p1[0], p1[1], depthPosition); + glVertex3f( p2[0], p2[1], depthPosition); glEnd(); // Draw orientation arrows if ( m_RenderOrientationArrows ) { this->DrawOrientationArrow( p2, p1, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); if ( preLastLineParam < 2 ) { // If we only have one line segment, draw other arrow, too this->DrawOrientationArrow( p1, p2, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); } } } } } else { Geometry2DDataToSurfaceFilter::Pointer surfaceCreator; SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast< SmartPointerProperty * >( GetDataNode()->GetProperty( "surfacegeometry", renderer)); if( (surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((surfaceCreator = dynamic_cast< Geometry2DDataToSurfaceFilter * >( surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull()) ) { surfaceCreator = Geometry2DDataToSurfaceFilter::New(); surfacecreatorprop = SmartPointerProperty::New(surfaceCreator); surfaceCreator->PlaceByGeometryOn(); GetDataNode()->SetProperty( "surfacegeometry", surfacecreatorprop ); } surfaceCreator->SetInput( input ); // Clip the Geometry2D with the reference geometry bounds (if available) if ( input->GetGeometry2D()->HasReferenceGeometry() ) { surfaceCreator->SetBoundingBox( input->GetGeometry2D()->GetReferenceGeometry()->GetBoundingBox() ); } int res; bool usegeometryparametricbounds = true; if ( GetDataNode()->GetIntProperty("xresolution", res, renderer)) { surfaceCreator->SetXResolution(res); usegeometryparametricbounds=false; } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { surfaceCreator->SetYResolution(res); usegeometryparametricbounds=false; } surfaceCreator->SetUseGeometryParametricBounds(usegeometryparametricbounds); // Calculate the surface of the Geometry2D surfaceCreator->Update(); if (m_SurfaceMapper.IsNull()) { m_SurfaceMapper=SurfaceGLMapper2D::New(); } m_SurfaceMapper->SetSurface(surfaceCreator->GetOutput()); m_SurfaceMapper->SetDataNode(GetDataNode()); m_SurfaceMapper->Paint(renderer); } } void mitk::Geometry2DDataMapper2D::DrawOrientationArrow( mitk::Point2D &outerPoint, mitk::Point2D &innerPoint, const mitk::PlaneGeometry *planeGeometry, const mitk::PlaneGeometry *rendererPlaneGeometry, const mitk::DisplayGeometry *displayGeometry, bool positiveOrientation ) { // Draw arrows to indicate plane orientation // Vector along line Vector2D v1 = innerPoint - outerPoint; v1.Normalize(); v1 *= 7.0; // Orthogonal vector Vector2D v2; v2[0] = v1[1]; v2[1] = -v1[0]; // Calculate triangle tip for one side and project it back into world // coordinates to determine whether it is above or below the plane Point2D worldPoint2D; Point3D worldPoint; displayGeometry->DisplayToWorld( outerPoint + v1 + v2, worldPoint2D ); rendererPlaneGeometry->Map( worldPoint2D, worldPoint ); // Initialize remaining triangle coordinates accordingly // (above/below state is XOR'ed with orientation flag) Point2D p1 = outerPoint + v1 * 2.0; Point2D p2 = outerPoint + v1 + ((positiveOrientation ^ planeGeometry->IsAbove( worldPoint )) ? v2 : -v2); // Draw the arrow (triangle) glBegin( GL_TRIANGLES ); glVertex2f( outerPoint[0], outerPoint[1] ); glVertex2f( p1[0], p1[1] ); glVertex2f( p2[0], p2[1] ); glEnd(); } void mitk::Geometry2DDataMapper2D::ApplyProperties( BaseRenderer *renderer ) { Superclass::ApplyProperties(renderer); PlaneOrientationProperty* decorationProperty; this->GetDataNode()->GetProperty( decorationProperty, "decoration", renderer ); if ( decorationProperty != NULL ) { if ( decorationProperty->GetPlaneDecoration() == PlaneOrientationProperty::PLANE_DECORATION_POSITIVE_ORIENTATION ) { m_RenderOrientationArrows = true; m_ArrowOrientationPositive = true; } else if ( decorationProperty->GetPlaneDecoration() == PlaneOrientationProperty::PLANE_DECORATION_NEGATIVE_ORIENTATION ) { m_RenderOrientationArrows = true; m_ArrowOrientationPositive = false; } else { m_RenderOrientationArrows = false; } } } void mitk::Geometry2DDataMapper2D::SetDatastorageAndGeometryBaseNode( mitk::DataStorage::Pointer ds, mitk::DataNode::Pointer parent ) { if (ds.IsNotNull()) { m_DataStorage = ds; } if (parent.IsNotNull()) { m_ParentNode = parent; } } diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp index a1db358e74..02e1198a73 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp @@ -1,708 +1,699 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkGeometry2DDataVtkMapper3D.h" -#include "mitkImageMapperGL2D.h" +#include "mitkImageVtkMapper2D.h" #include "mitkLookupTableProperty.h" #include "mitkSmartPointerProperty.h" #include "mitkSurface.h" #include "mitkVtkRepresentationProperty.h" #include "mitkWeakPointerProperty.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateOr.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { Geometry2DDataVtkMapper3D::Geometry2DDataVtkMapper3D() : m_NormalsActorAdded(false), m_DataStorage(NULL) { m_EdgeTuber = vtkTubeFilter::New(); m_EdgeMapper = vtkPolyDataMapper::New(); m_SurfaceCreator = Geometry2DDataToSurfaceFilter::New(); m_SurfaceCreatorBoundingBox = BoundingBox::New(); m_SurfaceCreatorPointsContainer = BoundingBox::PointsContainer::New(); m_Edges = vtkFeatureEdges::New(); m_Edges->BoundaryEdgesOn(); m_Edges->FeatureEdgesOff(); m_Edges->NonManifoldEdgesOff(); m_Edges->ManifoldEdgesOff(); m_EdgeTransformer = vtkTransformPolyDataFilter::New(); m_NormalsTransformer = vtkTransformPolyDataFilter::New(); m_EdgeActor = vtkActor::New(); m_BackgroundMapper = vtkPolyDataMapper::New(); m_BackgroundActor = vtkActor::New(); m_Prop3DAssembly = vtkAssembly::New(); m_ImageAssembly = vtkAssembly::New(); m_SurfaceCreatorBoundingBox->SetPoints( m_SurfaceCreatorPointsContainer ); m_Cleaner = vtkCleanPolyData::New(); m_Cleaner->PieceInvariantOn(); m_Cleaner->ConvertLinesToPointsOn(); m_Cleaner->ConvertPolysToLinesOn(); m_Cleaner->ConvertStripsToPolysOn(); m_Cleaner->PointMergingOn(); // Make sure that the FeatureEdge algorithm is initialized with a "valid" // (though empty) input vtkPolyData *emptyPolyData = vtkPolyData::New(); m_Cleaner->SetInput( emptyPolyData ); emptyPolyData->Delete(); m_Edges->SetInput(m_Cleaner->GetOutput()); m_EdgeTransformer->SetInput( m_Edges->GetOutput() ); m_EdgeTuber->SetInput( m_EdgeTransformer->GetOutput() ); m_EdgeTuber->SetVaryRadiusToVaryRadiusOff(); m_EdgeTuber->SetNumberOfSides( 12 ); m_EdgeTuber->CappingOn(); m_EdgeMapper->SetInput( m_EdgeTuber->GetOutput() ); m_EdgeMapper->ScalarVisibilityOff(); m_BackgroundMapper->SetInput(emptyPolyData); m_EdgeActor->SetMapper( m_EdgeMapper ); m_BackgroundActor->GetProperty()->SetAmbient( 0.5 ); m_BackgroundActor->GetProperty()->SetColor( 0.0, 0.0, 0.0 ); m_BackgroundActor->GetProperty()->SetOpacity( 1.0 ); m_BackgroundActor->SetMapper( m_BackgroundMapper ); vtkProperty * backfaceProperty = m_BackgroundActor->MakeProperty(); backfaceProperty->SetColor( 0.0, 0.0, 0.0 ); m_BackgroundActor->SetBackfaceProperty( backfaceProperty ); backfaceProperty->Delete(); m_FrontHedgeHog = vtkHedgeHog::New(); m_BackHedgeHog = vtkHedgeHog::New(); m_FrontNormalsMapper = vtkPolyDataMapper::New(); m_FrontNormalsMapper->SetInput( m_FrontHedgeHog->GetOutput() ); m_BackNormalsMapper = vtkPolyDataMapper::New(); m_Prop3DAssembly->AddPart( m_EdgeActor ); m_Prop3DAssembly->AddPart( m_ImageAssembly ); m_FrontNormalsActor = vtkActor::New(); m_FrontNormalsActor->SetMapper(m_FrontNormalsMapper); m_BackNormalsActor = vtkActor::New(); m_BackNormalsActor->SetMapper(m_BackNormalsMapper); m_DefaultLookupTable = vtkLookupTable::New(); m_DefaultLookupTable->SetTableRange( -1024.0, 4096.0 ); m_DefaultLookupTable->SetSaturationRange( 0.0, 0.0 ); m_DefaultLookupTable->SetHueRange( 0.0, 0.0 ); m_DefaultLookupTable->SetValueRange( 0.0, 1.0 ); m_DefaultLookupTable->Build(); m_DefaultLookupTable->SetTableValue( 0, 0.0, 0.0, 0.0, 0.0 ); m_ImageMapperDeletedCommand = MemberCommandType::New(); m_ImageMapperDeletedCommand->SetCallbackFunction( this, &Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback ); } Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D() { m_ImageAssembly->Delete(); m_Prop3DAssembly->Delete(); m_EdgeTuber->Delete(); m_EdgeMapper->Delete(); m_EdgeTransformer->Delete(); m_Cleaner->Delete(); m_Edges->Delete(); m_NormalsTransformer->Delete(); m_EdgeActor->Delete(); m_BackgroundMapper->Delete(); m_BackgroundActor->Delete(); m_DefaultLookupTable->Delete(); m_FrontNormalsMapper->Delete(); m_FrontNormalsActor->Delete(); m_FrontHedgeHog->Delete(); m_BackNormalsMapper->Delete(); m_BackNormalsActor->Delete(); m_BackHedgeHog->Delete(); // Delete entries in m_ImageActors list one by one m_ImageActors.clear(); LookupTablePropertiesList::iterator it; for(it = m_LookupTableProperties.begin(); it != m_LookupTableProperties.end();++it) { if ( it->second.LookupTableSource != NULL ) { it->second.LookupTableSource->Delete(); it->second.LookupTableSource = NULL; } } m_DataStorage = NULL; } vtkProp* Geometry2DDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { if ( (this->GetDataNode() != NULL ) && (m_ImageAssembly != NULL) ) { // Do not transform the entire Prop3D assembly, but only the image part // here. The colored frame is transformed elsewhere (via m_EdgeTransformer), // since only vertices should be transformed there, not the poly data // itself, to avoid distortion for anisotropic datasets. m_ImageAssembly->SetUserTransform( this->GetDataNode()->GetVtkTransform() ); } return m_Prop3DAssembly; } void Geometry2DDataVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { m_ImageAssembly->SetUserTransform( this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); } const Geometry2DData* Geometry2DDataVtkMapper3D::GetInput() { return static_cast ( GetData() ); } void Geometry2DDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage* storage) { if(storage != NULL && m_DataStorage != storage ) { m_DataStorage = storage; this->Modified(); } } void Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback( itk::Object *caller, const itk::EventObject& /*event*/ ) { - ImageMapperGL2D *imageMapper = dynamic_cast< ImageMapperGL2D * >( caller ); + ImageVtkMapper2D *imageMapper = dynamic_cast< ImageVtkMapper2D * >( caller ); if ( (imageMapper != NULL) ) { if ( m_ImageActors.count( imageMapper ) > 0) { m_ImageActors[imageMapper].m_Sender = NULL; // sender is already destroying itself m_ImageActors.erase( imageMapper ); } if ( m_LookupTableProperties.count( imageMapper ) > 0 ) { m_LookupTableProperties[imageMapper].LookupTableSource->Delete(); m_LookupTableProperties.erase( imageMapper ); } } } void Geometry2DDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { SetVtkMapperImmediateModeRendering(m_EdgeMapper); SetVtkMapperImmediateModeRendering(m_BackgroundMapper); // Remove all actors from the assembly, and re-initialize it with the // edge actor m_ImageAssembly->GetParts()->RemoveAllItems(); if ( !this->IsVisible(renderer) ) { // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOff(); m_EdgeActor->VisibilityOff(); return; } // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOn(); m_EdgeActor->VisibilityOn(); Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput()); if (input.IsNotNull() && (input->GetGeometry2D() != NULL)) { SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer)); if ( (surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((m_SurfaceCreator = dynamic_cast (surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull() ) ) { m_SurfaceCreator->PlaceByGeometryOn(); surfacecreatorprop = SmartPointerProperty::New( m_SurfaceCreator ); GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop); } m_SurfaceCreator->SetInput(input); int res; if (GetDataNode()->GetIntProperty("xresolution", res, renderer)) { m_SurfaceCreator->SetXResolution(res); } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { m_SurfaceCreator->SetYResolution(res); } double tubeRadius = 1.0; // Radius of tubular edge surrounding plane // Clip the Geometry2D with the reference geometry bounds (if available) if ( input->GetGeometry2D()->HasReferenceGeometry() ) { Geometry3D *referenceGeometry = input->GetGeometry2D()->GetReferenceGeometry(); BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if ( referenceGeometry->GetImageGeometry() ) { for ( unsigned int i = 0; i < 3; ++i ) { boundingBoxMin[i] -= 0.5; boundingBoxMax[i] -= 0.5; } } m_SurfaceCreatorPointsContainer->CreateElementAt( 0 ) = boundingBoxMin; m_SurfaceCreatorPointsContainer->CreateElementAt( 1 ) = boundingBoxMax; m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox ); tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; } // If no reference geometry is available, clip with the current global // bounds else if (m_DataStorage.IsNotNull()) { m_SurfaceCreator->SetBoundingBox(m_DataStorage->ComputeVisibleBoundingBox(NULL, "includeInBoundingBox")); tubeRadius = sqrt( m_SurfaceCreator->GetBoundingBox()->GetDiagonalLength2() ) / 450.0; } // Calculate the surface of the Geometry2D m_SurfaceCreator->Update(); Surface *surface = m_SurfaceCreator->GetOutput(); // Check if there's something to display, otherwise return if ( (surface->GetVtkPolyData() == 0 ) || (surface->GetVtkPolyData()->GetNumberOfCells() == 0) ) { m_ImageAssembly->VisibilityOff(); return; } // add a graphical representation of the surface normals if requested DataNode* node = this->GetDataNode(); bool displayNormals = false; bool colorTwoSides = false; bool invertNormals = false; node->GetBoolProperty("draw normals 3D", displayNormals, renderer); node->GetBoolProperty("color two sides", colorTwoSides, renderer); node->GetBoolProperty("invert normals", invertNormals, renderer); //if we want to draw the display normals or render two sides we have to get the colors if( displayNormals || colorTwoSides ) { //get colors float frontColor[3] = { 0.0, 0.0, 1.0 }; node->GetColor( frontColor, renderer, "front color" ); float backColor[3] = { 1.0, 0.0, 0.0 }; node->GetColor( backColor, renderer, "back color" ); if ( displayNormals ) { m_NormalsTransformer->SetInput( surface->GetVtkPolyData() ); m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) ); m_FrontHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); m_FrontHedgeHog->SetVectorModeToUseNormal(); m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 ); m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); m_BackHedgeHog->SetVectorModeToUseNormal(); m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 ); m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); //if there is no actor added yet, add one if ( !m_NormalsActorAdded ) { m_Prop3DAssembly->AddPart( m_FrontNormalsActor ); m_Prop3DAssembly->AddPart( m_BackNormalsActor ); m_NormalsActorAdded = true; } } //if we don't want to display normals AND there is an actor added remove the actor else if ( m_NormalsActorAdded ) { m_Prop3DAssembly->RemovePart( m_FrontNormalsActor ); m_Prop3DAssembly->RemovePart( m_BackNormalsActor ); m_NormalsActorAdded = false; } if ( colorTwoSides ) { if ( !invertNormals ) { m_BackgroundActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); } else { m_BackgroundActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); } } } // Add black background for all images (which may be transparent) m_BackgroundMapper->SetInput( surface->GetVtkPolyData() ); m_ImageAssembly->AddPart( m_BackgroundActor ); LayerSortedActorList layerSortedActors; // Traverse the data tree to find nodes resliced by ImageMapperGL2D mitk::NodePredicateOr::Pointer p = mitk::NodePredicateOr::New(); //use a predicate to get all data nodes which are "images" or inherit from mitk::Image mitk::TNodePredicateDataType< mitk::Image >::Pointer predicateAllImages = mitk::TNodePredicateDataType< mitk::Image >::New(); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(predicateAllImages); //process all found images for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode *node = it->Value(); if (node != NULL) this->ProcessNode(node, renderer, surface, layerSortedActors); } // Add all image actors to the assembly, sorted according to // layer property LayerSortedActorList::iterator actorIt; for ( actorIt = layerSortedActors.begin(); actorIt != layerSortedActors.end(); ++actorIt ) { m_ImageAssembly->AddPart( actorIt->second ); } // Configurate the tube-shaped frame: size according to the surface // bounds, color as specified in the plane's properties vtkPolyData *surfacePolyData = surface->GetVtkPolyData(); m_Cleaner->SetInput(surfacePolyData); m_EdgeTransformer->SetTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); // Adjust the radius according to extent m_EdgeTuber->SetRadius( tubeRadius ); // Get the plane's color and set the tube properties accordingly ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast(this->GetDataNode()->GetProperty( "color" )); if ( colorProperty.IsNotNull() ) { const Color& color = colorProperty->GetColor(); m_EdgeActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue()); } else { m_EdgeActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 ); } m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); } VtkRepresentationProperty* representationProperty; this->GetDataNode()->GetProperty(representationProperty, "material.representation", renderer); if ( representationProperty != NULL ) m_BackgroundActor->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() ); } void Geometry2DDataVtkMapper3D::ProcessNode( DataNode * node, BaseRenderer* renderer, Surface * surface, LayerSortedActorList &layerSortedActors ) { if ( node != NULL ) { //we need to get the information from the 2D mapper to render the texture on the 3D plane - ImageMapperGL2D *imageMapper = dynamic_cast< ImageMapperGL2D * >( node->GetMapper(1) ); //GetMapper(1) provides the 2D mapper for the data node + ImageVtkMapper2D *imageMapper = dynamic_cast< ImageVtkMapper2D * >( node->GetMapper(1) ); //GetMapper(1) provides the 2D mapper for the data node //if there is a 2D mapper, which is not the standard image mapper... if(!imageMapper && node->GetMapper(1)) { //... check if it is the composite mapper std::string cname(node->GetMapper(1)->GetNameOfClass()); if(!cname.compare("CompositeMapper")) //string.compare returns 0 if the two strings are equal. { //get the standard image mapper. //This is a special case in MITK and does only work for the CompositeMapper. - imageMapper = dynamic_cast( node->GetMapper(3) ); + imageMapper = dynamic_cast( node->GetMapper(3) ); } } if ( (node->IsVisible(renderer)) && imageMapper ) { WeakPointerProperty::Pointer rendererProp = dynamic_cast< WeakPointerProperty * >(GetDataNode()->GetPropertyList()->GetProperty("renderer")); if ( rendererProp.IsNotNull() ) { BaseRenderer::Pointer planeRenderer = dynamic_cast< BaseRenderer * >(rendererProp->GetWeakPointer().GetPointer()); if ( planeRenderer.IsNotNull() ) { // If it has not been initialized already in a previous pass, // generate an actor, a lookup table and a texture object to // render the image associated with the ImageMapperGL2D. vtkActor *imageActor; vtkDataSetMapper *dataSetMapper = NULL; vtkLookupTable *lookupTable; vtkTexture *texture; if ( m_ImageActors.count( imageMapper ) == 0 ) { dataSetMapper = vtkDataSetMapper::New(); //Enable rendering without copying the image. dataSetMapper->ImmediateModeRenderingOn(); lookupTable = vtkLookupTable::New(); lookupTable->DeepCopy( m_DefaultLookupTable ); texture = vtkTexture::New(); texture->SetLookupTable( lookupTable ); texture->RepeatOff(); imageActor = vtkActor::New(); imageActor->GetProperty()->SetAmbient( 0.5 ); imageActor->SetMapper( dataSetMapper ); imageActor->SetTexture( texture ); // Make imageActor the sole owner of the mapper and texture // objects lookupTable->UnRegister( NULL ); dataSetMapper->UnRegister( NULL ); texture->UnRegister( NULL ); // Store the actor so that it may be accessed in following // passes. m_ImageActors[imageMapper].Initialize(imageActor, imageMapper, m_ImageMapperDeletedCommand); } else { // Else, retrieve the actor and associated objects from the // previous pass. imageActor = m_ImageActors[imageMapper].m_Actor; dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper(); texture = imageActor->GetTexture(); lookupTable = dynamic_cast(texture->GetLookupTable()); } // Set poly data new each time its object changes (e.g. when // switching between planar and curved geometries) if ( (dataSetMapper != NULL) && (dataSetMapper->GetInput() != surface->GetVtkPolyData()) ) { dataSetMapper->SetInput( surface->GetVtkPolyData() ); } imageActor->GetMapper()->GetInput()->Update(); imageActor->GetMapper()->Update(); - // We have to do this before GenerateAllData() is called - // since there may be no RendererInfo for renderer yet, - // thus GenerateAllData won't update the (non-existing) - // RendererInfo for renderer. By calling GetRendererInfo - // a RendererInfo will be created for renderer (if it does not - // exist yet). - imageMapper->GetRendererInfo( planeRenderer ); - imageMapper->GenerateAllData(); - // ensure the right openGL context, as 3D widgets may render and take their plane texture from 2D image mappers renderer->GetRenderWindow()->MakeCurrent(); // Retrieve and update image to be mapped - const ImageMapperGL2D::RendererInfo *rit = imageMapper->GetRendererInfo( planeRenderer ); - if(rit->m_Image != NULL) - { - rit->m_Image->Update(); - //set the 2D image as texture for the 3D plane - texture->SetInput( rit->m_Image ); + const ImageVtkMapper2D::LocalStorage* localStorage = imageMapper->m_LSH.GetLocalStorage(planeRenderer); + + if(localStorage->m_ReslicedImage != NULL) + { + localStorage->m_ReslicedImage->Update(); + texture->SetInput( localStorage->m_ReslicedImage ); //default level window ScalarType windowMin = 0.0; ScalarType windowMax = 255.0; LevelWindow levelWindow; bool binary = false; node->GetBoolProperty( "binary", binary, renderer ); // check for "use color" bool useColor = false; node->GetBoolProperty( "use color", useColor, planeRenderer ); // VTK (mis-)interprets unsigned char (binary) images as color images; // So, we must manually turn on their mapping through a (gray scale) lookup table; texture->SetMapColorScalarsThroughLookupTable(binary); //if we have a binary image, the range is just 0 to 1 if( binary ) { windowMin = 0; windowMax = 1; useColor = true; } // check for level-window-prop and use it if it exists if( !binary && ( node->GetLevelWindow( levelWindow, planeRenderer, "levelWindow" ) || node->GetLevelWindow( levelWindow, planeRenderer ) ) ) { windowMin = levelWindow.GetLowerWindowBound(); windowMax = levelWindow.GetUpperWindowBound(); } vtkLookupTable *lookupTableSource; // check for LookupTable LookupTableProperty::Pointer lookupTableProp; lookupTableProp = dynamic_cast< LookupTableProperty * >(node->GetPropertyList()->GetProperty( "LookupTable" )); // If there is a lookup table supplied and we don't // want to use the color property, use it; //otherwise, use the default grayscale table if ( lookupTableProp.IsNotNull() && !useColor ) { lookupTableSource = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { lookupTableSource = m_DefaultLookupTable; } LookupTableProperties &lutProperties = m_LookupTableProperties[imageMapper]; // If there has been some change since the last pass which // makes it necessary to re-build the lookup table, do it. if ( (lutProperties.LookupTableSource != lookupTableSource) || (lutProperties.windowMin != windowMin) || (lutProperties.windowMax != windowMax) ) { // Note the values for the next pass (lutProperties is a // reference to the list entry!) if ( lutProperties.LookupTableSource != NULL ) { lutProperties.LookupTableSource->Delete(); } lutProperties.LookupTableSource = lookupTableSource; lutProperties.LookupTableSource->Register( NULL ); lutProperties.windowMin = windowMin; lutProperties.windowMax = windowMax; lookupTable->DeepCopy( lookupTableSource ); lookupTable->SetRange( windowMin, windowMax ); } //get the color float rgb[3] = { 1.0, 1.0, 1.0 }; node->GetColor( rgb, renderer ); // Apply color property (of the node, not of the plane) // if we want to use the color if(useColor) { imageActor->GetProperty()->SetColor( rgb[0], rgb[1], rgb[2] ); } else //else default color = white to avoid site effects from the lookuptable { imageActor->GetProperty()->SetColor( 1, 1, 1 ); } // Apply opacity property (of the node, not of the plane) float opacity = 0.999; node->GetOpacity( opacity, renderer ); imageActor->GetProperty()->SetOpacity( opacity ); // Set texture interpolation on/off bool textureInterpolation = node->IsOn( "texture interpolation", renderer ); texture->SetInterpolate( textureInterpolation ); // Store this actor to be added to the actor assembly, sort // by layer int layer = 1; node->GetIntProperty( "layer", layer ); layerSortedActors.insert(std::pair< int, vtkActor * >( layer, imageActor ) ); } } } } } } void Geometry2DDataVtkMapper3D::ActorInfo::Initialize(vtkActor* actor, itk::Object* sender, itk::Command* command) { m_Actor = actor; m_Sender = sender; // Get informed when ImageMapper object is deleted, so that // the data structures built here can be deleted as well m_ObserverID = sender->AddObserver( itk::DeleteEvent(), command ); } Geometry2DDataVtkMapper3D::ActorInfo::ActorInfo() : m_Actor(NULL), m_Sender(NULL), m_ObserverID(0) { } Geometry2DDataVtkMapper3D::ActorInfo::~ActorInfo() { if(m_Sender != NULL) { m_Sender->RemoveObserver(m_ObserverID); } if(m_Actor != NULL) { m_Actor->Delete(); } } } // namespace mitk diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h index b48fd24c4e..7c6f12efe2 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h @@ -1,234 +1,234 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F #define MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F #include #include "mitkVtkMapper3D.h" #include "mitkDataStorage.h" #include "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkWeakPointer.h" #include #include class vtkActor; class vtkPolyDataMapper; class vtkDataSetMapper; class vtkLookupTable; class vtkAssembly; class vtkFeatureEdges; class vtkTubeFilter; class vtkTransformPolyDataFilter; class vtkHedgeHog; namespace mitk { class Geometry2DData; class BaseRenderer; -class ImageMapperGL2D; +class ImageVtkMapper2D; class DataStorage; /** * \brief Vtk-based mapper to display a Geometry2D in a 3D window * \ingroup Mapper * * Uses a Geometry2DDataToSurfaceFilter object to create a vtkPolyData representation of a given Geometry2D instance. * Geometry2D may either contain a common flat plane or a curved plane (ThinPlateSplineCurvedGeometry). * * The vtkPolyData object is then decorated by a colored tube on the edges and by image textures if possible * (currently this requires that there is a 2D render window rendering the same geometry as this mapper). * * Properties that influence rendering are: * * - \b "color": (ColorProperty) Color of the tubed frame. * - \b "xresolution": (FloatProperty) Resolution (=number of tiles) in x direction. Only relevant for ThinPlateSplineCurvedGeometry * - \b "yresolution": (FloatProperty) Resolution (=number of tiles) in y direction. Only relevant for ThinPlateSplineCurvedGeometry * - \b "draw normals 3D": (BoolProperty) If true, a vtkHedgeHog is used to display normals for the generated surface object. Useful to distinguish front and back of a plane. Hedgehogs are colored according to "front color" and "back color" * - \b "color two sides": (BoolProperty) If true, front and back side of the plane are colored differently ("front color" and "back color") * - \b "invert normals": (BoolProperty) Inverts front/back for display. * - \b "front color": (ColorProperty) Color for front side of the plane * - \b "back color": (ColorProperty) Color for back side of the plane * - \b "material.representation": (BoolProperty) Choose the representation to draw the mesh in (Surface, Wireframe, Point Cloud) * - \b "surfacegeometry": TODO: Add documentation * - \b "LookupTable": (LookupTableProperty) Set the lookuptable to render with. * * Note: The following properties are set for each image individually, and thus, also influence the rendering of this mapper: * * - \b "texture interpolation": (BoolProperty) Turn on/off the texture interpolation of each image * - \b "use color": (BoolProperty) Decide whether we want to use the color property or a lookuptable. * - \b "binary": (BoolProperty) Binary image handling: Color the value=1.0 with the color property and make the background (value=0.0) of the image translucent. * - \b "layer": (IntProperty) Controls what image is considered "on top" of another. In the case that two should inhabit the same space, higher layer occludes lower layer. * - \b "opacity": (FloatProperty) Set the opacity for each rendered image. * - \b "color": (FloatProperty) Set the color for each rendered image. * * The internal filter pipeline which combines a (sometimes deformed) 2D surface * with a nice frame and image textures is illustrated in the following sketch: * * \image html mitkGeometry2DDataVtkMapper3D.png "Internal filter pipeline" * */ class MITK_CORE_EXPORT Geometry2DDataVtkMapper3D : public VtkMapper3D { public: mitkClassMacro(Geometry2DDataVtkMapper3D, VtkMapper3D); itkNewMacro(Geometry2DDataVtkMapper3D); /** * Overloaded since the displayed color-frame of the image mustn't be * transformed after generation of poly data, but before (vertex coordinates * only) */ virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); /** * \brief Get the Geometry2DData to map */ virtual const Geometry2DData *GetInput(); /** * \brief All images found when traversing the (sub-) tree starting at - * \a iterator which are resliced by an ImageMapperGL2D will be mapped. + * \a iterator which are resliced by an ImageVtkMapper2D will be mapped. * This method is used to set the data storage to traverse. This offers * the possibility to use this mapper for other data storages (not only * the default data storage). */ virtual void SetDataStorageForTexture(mitk::DataStorage* storage); protected: typedef std::multimap< int, vtkActor * > LayerSortedActorList; Geometry2DDataVtkMapper3D(); virtual ~Geometry2DDataVtkMapper3D(); virtual void GenerateDataForRenderer(BaseRenderer* renderer); void ProcessNode( DataNode * node, BaseRenderer* renderer, Surface * surface, LayerSortedActorList &layerSortedActors ); void ImageMapperDeletedCallback( itk::Object *caller, const itk::EventObject &event ); /** \brief general PropAssembly to hold the entire scene */ vtkAssembly *m_Prop3DAssembly; /** \brief PropAssembly to hold the planes */ vtkAssembly *m_ImageAssembly; Geometry2DDataToSurfaceFilter::Pointer m_SurfaceCreator; BoundingBox::Pointer m_SurfaceCreatorBoundingBox; BoundingBox::PointsContainer::Pointer m_SurfaceCreatorPointsContainer; /** \brief Edge extractor for tube-shaped frame */ vtkFeatureEdges *m_Edges; /** \brief Filter to apply object transform to the extracted edges */ vtkTransformPolyDataFilter *m_EdgeTransformer; /** \brief Source to create the tube-shaped frame */ vtkTubeFilter *m_EdgeTuber; /** \brief Mapper for the tube-shaped frame */ vtkPolyDataMapper *m_EdgeMapper; /** \brief Actor for the tube-shaped frame */ vtkActor *m_EdgeActor; /** \brief Mapper for black plane background */ vtkPolyDataMapper *m_BackgroundMapper; /** \brief Actor for black plane background */ vtkActor *m_BackgroundActor; /** \brief Transforms the suface before applying the glyph filter */ vtkTransformPolyDataFilter* m_NormalsTransformer; /** \brief Mapper for normals representation (thin lines) */ vtkPolyDataMapper* m_FrontNormalsMapper; vtkPolyDataMapper* m_BackNormalsMapper; /** \brief Generates lines for surface normals */ vtkHedgeHog* m_FrontHedgeHog; vtkHedgeHog* m_BackHedgeHog; /** \brief Actor to hold the normals arrows */ vtkActor* m_FrontNormalsActor; vtkActor* m_BackNormalsActor; /** Cleans the polyline in order to avoid phantom boundaries */ vtkCleanPolyData *m_Cleaner; /** Internal flag, if actors for normals are already added to m_Prop3DAssembly*/ bool m_NormalsActorAdded; /** \brief The DataStorage defines which part of the data tree is traversed for renderering. */ mitk::WeakPointer m_DataStorage; /** A default grayscale lookup-table, used for reference */ vtkLookupTable *m_DefaultLookupTable; class MITK_CORE_EXPORT ActorInfo { public: vtkActor * m_Actor; // we do not need a smart-pointer, because we delete our // connection, when the referenced mapper is destroyed itk::Object* m_Sender; unsigned long m_ObserverID; void Initialize(vtkActor* actor, itk::Object* sender, itk::Command* command); ActorInfo(); ~ActorInfo(); }; /** \brief List holding the vtkActor to map the image into 3D for each * ImageMapper */ - typedef std::map< ImageMapperGL2D *, ActorInfo > ActorList; + typedef std::map< ImageVtkMapper2D *, ActorInfo > ActorList; ActorList m_ImageActors; struct LookupTableProperties { LookupTableProperties() : LookupTableSource( NULL ), windowMin( 0.0 ), windowMax( 4096.0 ) {} vtkLookupTable *LookupTableSource; vtkFloatingPointType windowMin; vtkFloatingPointType windowMax; }; - typedef std::map< ImageMapperGL2D *, LookupTableProperties > + typedef std::map< ImageVtkMapper2D *, LookupTableProperties > LookupTablePropertiesList; /** \brief List holding some lookup table properties of the previous pass */ LookupTablePropertiesList m_LookupTableProperties; // responsiblity to remove the observer upon its destruction typedef itk::MemberCommand< Geometry2DDataVtkMapper3D > MemberCommandType; MemberCommandType::Pointer m_ImageMapperDeletedCommand; }; } // namespace mitk #endif /* MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F */ diff --git a/Core/Code/Rendering/mitkImageMapperGL2D.cpp b/Core/Code/Rendering/mitkImageMapperGL2D.cpp deleted file mode 100644 index c1034bd724..0000000000 --- a/Core/Code/Rendering/mitkImageMapperGL2D.cpp +++ /dev/null @@ -1,1395 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. - -=========================================================================*/ - -#include "mitkImageMapperGL2D.h" -#include "widget.h" -#include "picimage.h" -#include "pic2vtk.h" -#include "mitkTimeSlicedGeometry.h" -#include "mitkPlaneGeometry.h" -#include "mitkDataNode.h" -#include "mitkVtkPropRenderer.h" -#include "mitkLookupTableProperty.h" -#include "mitkProperties.h" -#include "mitkLevelWindowProperty.h" -#include "mitkVtkResliceInterpolationProperty.h" -#include "mitkVolumeCalculator.h" -#include "mitkImageSliceSelector.h" - -#include "mitkAbstractTransformGeometry.h" -#include "mitkDataNodeFactory.h" - -#include "mitkResliceMethodProperty.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vtkMitkThickSlicesFilter.h" -#include "itkRGBAPixel.h" - - -int mitk::ImageMapperGL2D::numRenderer = 0; - -mitk::ImageMapperGL2D::ImageMapperGL2D() -{ -} - - -mitk::ImageMapperGL2D::~ImageMapperGL2D() -{ - this->Clear(); - this->InvokeEvent( itk::DeleteEvent() ); -} - - -void -mitk::ImageMapperGL2D::Paint( mitk::BaseRenderer *renderer ) -{ - if ( !this->IsVisible( renderer ) ) - { - return; - } - - this->Update( renderer ); - - RendererInfo &rendererInfo = this->AccessRendererInfo( renderer ); - iil4mitkPicImage *image = rendererInfo.Get_iil4mitkImage(); - - if ( ( image == NULL ) || ( image->image() == NULL ) ) - { - return; - } - - const mitk::DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); - - Vector2D topLeft = displayGeometry->GetOriginInMM(); - Vector2D bottomRight = topLeft + displayGeometry->GetSizeInMM(); - - topLeft[0] *= rendererInfo.m_PixelsPerMM[0]; - topLeft[1] *= rendererInfo.m_PixelsPerMM[1]; - - bottomRight[0] *= rendererInfo.m_PixelsPerMM[0]; - bottomRight[1] *= rendererInfo.m_PixelsPerMM[1]; - - topLeft += rendererInfo.m_Overlap; - bottomRight += rendererInfo.m_Overlap; - - Vector2D diag = ( topLeft - bottomRight ); - //float size = diag.GetNorm(); - - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( topLeft[0], bottomRight[0], topLeft[1], bottomRight[1], 0.0, 1.0 ); - glMatrixMode( GL_MODELVIEW ); - glDepthMask(GL_FALSE); - - // Define clipping planes to clip the image according to the bounds - // correlating to the current world geometry. The "extent" of the bounds - // needs to be enlarged by an "overlap" factor, in order to make the - // remaining area are large enough to cover rotated planes also. - // - // Note that this can be improved on, by not merely using a large enough - // rectangle for clipping, but using the side surfaces of the transformed - // 3D bounds as clipping planes instead. This would clip even rotates - // planes at their exact intersection lines with the 3D bounding box. - //GLdouble eqn0[4] = { 1.0, 0.0, 0.0, 0.0 }; - //GLdouble eqn1[4] = { -1.0, 0.0, 0.0, rendererInfo.m_Extent[0] - // + 2.0 * rendererInfo.m_Overlap[0]/* - rendererInfo.m_PixelsPerMM[0]*/ }; - //MITK_INFO << "X: " << rendererInfo.m_Extent[0] - // + 2.0 * rendererInfo.m_Overlap[0] - rendererInfo.m_PixelsPerMM[0] << std::endl; - - //GLdouble eqn2[4] = { 0.0, 1.0, 0.0, 0.0 }; - //GLdouble eqn3[4] = { 0.0, -1.0, 0.0, rendererInfo.m_Extent[1] - // + 2.0 * rendererInfo.m_Overlap[1]/* - rendererInfo.m_PixelsPerMM[1]*/ }; - //MITK_INFO << "Y:" << rendererInfo.m_Extent[1] - // + 2.0 * rendererInfo.m_Overlap[1] - rendererInfo.m_PixelsPerMM[1] << std::endl; - - // IW commented out the previous lines and reverted to rev. 9358 - // (version before rev. 9443) See bug #625 - GLdouble eqn0[4] = {0.0, 1.0, 0.0, 0.0}; - GLdouble eqn1[4] = {1.0, 0.0, 0.0, 0.0}; - GLdouble eqn2[4] = {-1.0, 0.0 , 0.0, image->width()}; - GLdouble eqn3[4] = {0, -1.0, 0.0, image->height() }; - - glClipPlane( GL_CLIP_PLANE0, eqn0 ); - glEnable( GL_CLIP_PLANE0 ); - glClipPlane( GL_CLIP_PLANE1, eqn1 ); - glEnable( GL_CLIP_PLANE1 ); - glClipPlane( GL_CLIP_PLANE2, eqn2 ); - glEnable( GL_CLIP_PLANE2 ); - glClipPlane( GL_CLIP_PLANE3, eqn3 ); - glEnable( GL_CLIP_PLANE3 ); - - - // Render the image - image->setInterpolation( rendererInfo.m_TextureInterpolation ); - - - image->display( renderer->GetRenderWindow() ); - - - // Disable the utilized clipping planes - glDisable( GL_CLIP_PLANE0 ); - glDisable( GL_CLIP_PLANE1 ); - glDisable( GL_CLIP_PLANE2 ); - glDisable( GL_CLIP_PLANE3 ); - - - // display volume property, if it exists and should be displayed - bool shouldShowVolume = false, binary = false; - float segmentationVolume = -1.0; - - mitk::DataNode *node = this->GetDataNode(); - mitk::Image* mitkimage = dynamic_cast(node->GetData()); - - // Check if a volume in ml can be drawn in the image. - // This is the case if: - // 1. The property "showVolume" is true AND [ - // 2.1 The image has a volume stored as property (3D case) OR - // 2.2 The image is 3D or 4D and binary, so the volume can be calculated ] - if ( - (node->GetBoolProperty("showVolume", shouldShowVolume)) && - (shouldShowVolume) && - ( - (node->GetFloatProperty("volume", segmentationVolume) ) - || - (mitkimage != NULL && - mitkimage->GetDimension() >= 3 && - node->GetBoolProperty("binary", binary) && - binary) - ) - ) - { - // calculate screen position for text by searching for the object border - mitkIpPicDescriptor* pic = image->image(); - - // search object border in current slice - - unsigned int s_x = 0; - unsigned int s_y = 0; - unsigned int s_n = 0; - - for(unsigned int y=0;yn[1];y++) - for(unsigned int x=0;xn[0];x++) - { - bool set=false; - switch ( pic->bpe ) - { - case 8: { - mitkIpInt1_t *current = static_cast< mitkIpInt1_t *>( pic->data ); - current += y*pic->n[0] + x; - if(current[0]) set=true; - break; } - case 16: { - mitkIpInt2_t *current = static_cast< mitkIpInt2_t *>( pic->data ); - current += y*pic->n[0] + x; - if(current[0]) set=true; - break; } - case 24: { - mitkIpInt1_t *current = static_cast< mitkIpInt1_t *>( pic->data ); - current += ( y*pic->n[0] + x )*3; - if(current[0]||current[1]||current[2]) set=true; - break; } - } - if(set) - { - if ( x > s_x ) s_x = x; - if ( y > s_y ) s_y = y; - s_n++; - } - } - - // if an object has been found, draw annotation - if ( s_n>0 ) - { - // make sure a segmentation volume is present - if( segmentationVolume <= 0 ) - { - // if not, check if the image is truly binary - if( mitkimage->GetScalarValueMax( renderer->GetTimeStep() ) == 1 ) - { - // if yes, get the volume from image statistics - segmentationVolume = mitk::VolumeCalculator::ComputeVolume( - mitkimage->GetSlicedGeometry()->GetSpacing(), mitkimage->GetCountOfMaxValuedVoxelsNoRecompute(renderer->GetTimeStep())); - } - } - - // create text - std::stringstream volumeString; - int precision = 1; - if (segmentationVolume < 0.1) - precision = 4; - volumeString << std::fixed << std::setprecision(precision) << segmentationVolume; - - std::string unit; - if (node->GetStringProperty("volume annotation unit", unit)) - { - volumeString << " " << unit; - } - else - { - volumeString << " ml"; - } - - - // draw text - mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); - - //calc index pos - Point2D pt2D; - - pt2D[0] = s_x; - pt2D[1] = s_y; - - //calc index pos with spacing - const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); - - //calc display coord - worldGeometry->IndexToWorld( pt2D, pt2D ); - displayGeometry->WorldToDisplay( pt2D, pt2D ); - - mitk::ColorProperty::Pointer annotationColorProp; - mitk::Color annotationColor; - annotationColor.Set(0,1,0); - - if (node->GetProperty(annotationColorProp, "volume annotation color")) - { - annotationColor = annotationColorProp->GetColor(); - } - bool hover = false; - bool selected = false; - GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); - GetDataNode()->GetBoolProperty("selected", selected, renderer); - - if(hover) - { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.hoveringcolor", renderer)); - if(colorprop.IsNotNull()) - annotationColor = colorprop->GetColor(); - - } - if(selected) - { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.selectedcolor", renderer)); - if(colorprop.IsNotNull()) - annotationColor = colorprop->GetColor(); - - } - - OpenGLrenderer->WriteSimpleText(volumeString.str(), pt2D[0]+1, pt2D[1]-1,0,0,0); //this is a shadow - OpenGLrenderer->WriteSimpleText(volumeString.str(), pt2D[0] , pt2D[1] ,annotationColor.GetRed() - ,annotationColor.GetGreen() - ,annotationColor.GetBlue()); - } - - } - - //glPushMatrix(); - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( - 0.0, displayGeometry->GetDisplayWidth(), - 0.0, displayGeometry->GetDisplayHeight(), - 0.0, 1.0 - ); - - glDepthMask(GL_TRUE); - //glMatrixMode( GL_MODELVIEW ); - //glPopMatrix(); -} - - -const mitk::ImageMapperGL2D::InputImageType * -mitk::ImageMapperGL2D::GetInput( void ) -{ - return static_cast< const mitk::ImageMapperGL2D::InputImageType * >( this->GetData() ); -} - - -int -mitk::ImageMapperGL2D::GetAssociatedChannelNr( mitk::BaseRenderer *renderer ) -{ - RendererInfo &rendererInfo = this->AccessRendererInfo( renderer ); - - return rendererInfo.GetRendererID(); -} - - -void -mitk::ImageMapperGL2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) -{ - mitk::Image *input = const_cast< mitk::ImageMapperGL2D::InputImageType * >( - this->GetInput() - ); - input->Update(); - - if ( input == NULL ) - { - return; - } - - RendererInfo &rendererInfo = this->AccessRendererInfo( renderer ); - rendererInfo.Squeeze(); - - - iil4mitkPicImage *image = new iil4mitkPicImage( 512 ); - rendererInfo.Set_iil4mitkImage( image ); - - this->ApplyProperties( renderer ); - - const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); - - if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->GetReferenceGeometry() )) - { - return; - } - - // check if there is something to display. - if ( ! input->IsVolumeSet( this->GetTimestep() ) ) return; - - Image::RegionType requestedRegion = input->GetLargestPossibleRegion(); - requestedRegion.SetIndex( 3, this->GetTimestep() ); - requestedRegion.SetSize( 3, 1 ); - requestedRegion.SetSize( 4, 1 ); - input->SetRequestedRegion( &requestedRegion ); - input->Update(); - - vtkImageData* inputData = input->GetVtkImageData( this->GetTimestep() ); - - if ( inputData == NULL ) - { - return; - } - - vtkFloatingPointType spacing[3]; - inputData->GetSpacing( spacing ); - - // how big the area is in physical coordinates: widthInMM x heightInMM pixels - mitk::ScalarType widthInMM, heightInMM; - - // where we want to sample - Point3D origin; - Vector3D right, bottom, normal; - Vector3D rightInIndex, bottomInIndex; - - // take transform of input image into account - const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); - const Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( this->GetTimestep() ); - - ScalarType mmPerPixel[2]; - - - // Bounds information for reslicing (only reuqired if reference geometry - // is present) - vtkFloatingPointType bounds[6]; - bool boundsInitialized = false; - - for ( int i = 0; i < 6; ++i ) - { - bounds[i] = 0.0; - } - - // Do we have a simple PlaneGeometry? - if ( dynamic_cast< const PlaneGeometry * >( worldGeometry ) != NULL ) - { - const PlaneGeometry *planeGeometry = - static_cast< const PlaneGeometry * >( worldGeometry ); - - origin = planeGeometry->GetOrigin(); - right = planeGeometry->GetAxisVector( 0 ); - bottom = planeGeometry->GetAxisVector( 1 ); - normal = planeGeometry->GetNormal(); - - bool inPlaneResampleExtentByGeometry = false; - GetDataNode()->GetBoolProperty( - "in plane resample extent by geometry", - inPlaneResampleExtentByGeometry, renderer - ); - - if ( inPlaneResampleExtentByGeometry ) - { - // Resampling grid corresponds to the current world geometry. This - // means that the spacing of the output 2D image depends on the - // currently selected world geometry, and *not* on the image itself. - rendererInfo.m_Extent[0] = worldGeometry->GetExtent( 0 ); - rendererInfo.m_Extent[1] = worldGeometry->GetExtent( 1 ); - } - else - { - // Resampling grid corresponds to the input geometry. This means that - // the spacing of the output 2D image is directly derived from the - // associated input image, regardless of the currently selected world - // geometry. - inputGeometry->WorldToIndex( right, rightInIndex ); - inputGeometry->WorldToIndex( bottom, bottomInIndex ); - rendererInfo.m_Extent[0] = rightInIndex.GetNorm(); - rendererInfo.m_Extent[1] = bottomInIndex.GetNorm(); - } - - - // Get the extent of the current world geometry and calculate resampling - // spacing therefrom. - widthInMM = worldGeometry->GetExtentInMM( 0 ); - heightInMM = worldGeometry->GetExtentInMM( 1 ); - - mmPerPixel[0] = widthInMM / rendererInfo.m_Extent[0]; - mmPerPixel[1] = heightInMM / rendererInfo.m_Extent[1]; - - right.Normalize(); - bottom.Normalize(); - normal.Normalize(); - - origin += right * ( mmPerPixel[0] * 0.5 ); - origin += bottom * ( mmPerPixel[1] * 0.5 ); - - widthInMM -= mmPerPixel[0]; - heightInMM -= mmPerPixel[1]; - - // Use inverse transform of the input geometry for reslicing the 3D image - rendererInfo.m_Reslicer->SetResliceTransform( - inputGeometry->GetVtkTransform()->GetLinearInverse() ); - - // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) - rendererInfo.m_Reslicer->SetBackgroundLevel( -32768 ); - - - // If a reference geometry does exist (as would usually be the case for - // PlaneGeometry), store it in rendererInfo so that we have access to it - // in Paint. - // - // Note: this is currently not strictly required, but could facilitate - // correct plane clipping. - if ( worldGeometry->GetReferenceGeometry() ) - { - rendererInfo.m_ReferenceGeometry = worldGeometry->GetReferenceGeometry(); - - // Calculate the actual bounds of the transformed plane clipped by the - // dataset bounding box; this is required for drawing the texture at the - // correct position during 3D mapping. - - boundsInitialized = this->CalculateClippedPlaneBounds( - rendererInfo.m_ReferenceGeometry, planeGeometry, bounds ); - } - } - - // Do we have an AbstractTransformGeometry? - else if ( dynamic_cast< const AbstractTransformGeometry * >( worldGeometry ) ) - { - const mitk::AbstractTransformGeometry* abstractGeometry = - dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); - - rendererInfo.m_Extent[0] = abstractGeometry->GetParametricExtent(0); - rendererInfo.m_Extent[1] = abstractGeometry->GetParametricExtent(1); - - widthInMM = abstractGeometry->GetParametricExtentInMM(0); - heightInMM = abstractGeometry->GetParametricExtentInMM(1); - - mmPerPixel[0] = widthInMM / rendererInfo.m_Extent[0]; - mmPerPixel[1] = heightInMM / rendererInfo.m_Extent[1]; - - origin = abstractGeometry->GetPlane()->GetOrigin(); - - right = abstractGeometry->GetPlane()->GetAxisVector(0); - right.Normalize(); - - bottom = abstractGeometry->GetPlane()->GetAxisVector(1); - bottom.Normalize(); - - normal = abstractGeometry->GetPlane()->GetNormal(); - normal.Normalize(); - - // Use a combination of the InputGeometry *and* the possible non-rigid - // AbstractTransformGeometry for reslicing the 3D Image - vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); - composedResliceTransform->Identity(); - composedResliceTransform->Concatenate( - inputGeometry->GetVtkTransform()->GetLinearInverse() ); - composedResliceTransform->Concatenate( - abstractGeometry->GetVtkAbstractTransform() - ); - - rendererInfo.m_Reslicer->SetResliceTransform( composedResliceTransform ); - composedResliceTransform->UnRegister( NULL ); // decrease RC - - // Set background level to BLACK instead of translucent, to avoid - // boundary artifacts (see Geometry2DDataVtkMapper3D) - rendererInfo.m_Reslicer->SetBackgroundLevel( -1023 ); - } - else - { - return; - } - - - // Make sure that the image to display has a certain minimum size. - if ( (rendererInfo.m_Extent[0] <= 2) && (rendererInfo.m_Extent[1] <= 2) ) - { - return; - } - - // Initialize the interpolation mode for resampling; switch to nearest - // neighbor if the input image is too small. - if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) - { - VtkResliceInterpolationProperty *resliceInterpolationProperty; - this->GetDataNode()->GetProperty( - resliceInterpolationProperty, "reslice interpolation" ); - - int interpolationMode = VTK_RESLICE_NEAREST; - if ( resliceInterpolationProperty != NULL ) - { - interpolationMode = resliceInterpolationProperty->GetInterpolation(); - } - - switch ( interpolationMode ) - { - case VTK_RESLICE_NEAREST: - rendererInfo.m_Reslicer->SetInterpolationModeToNearestNeighbor(); - break; - - case VTK_RESLICE_LINEAR: - rendererInfo.m_Reslicer->SetInterpolationModeToLinear(); - break; - - case VTK_RESLICE_CUBIC: - rendererInfo.m_Reslicer->SetInterpolationModeToCubic(); - break; - } - } - else - { - rendererInfo.m_Reslicer->SetInterpolationModeToNearestNeighbor(); - } - - int thickSlicesMode = 0; - - int thickSlicesNum = 1; - - // Thick slices parameters - if( inputData->GetNumberOfScalarComponents() == 1 ) // for now only single component are allowed - { - DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); - if(dn) - { - ResliceMethodProperty *resliceMethodEnumProperty=0; - - if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) - thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); - - IntProperty *intProperty=0; - if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) - { - thickSlicesNum = intProperty->GetValue(); - if(thickSlicesNum < 1) thickSlicesNum=1; - if(thickSlicesNum > 100) thickSlicesNum=100; - } - } - else - { - MITK_WARN << "no associated widget plane data tree node found"; - } - } - - rendererInfo.m_UnitSpacingImageFilter->SetInput( inputData ); - rendererInfo.m_Reslicer->SetInput( rendererInfo.m_UnitSpacingImageFilter->GetOutput() ); - //rendererInfo.m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); - //rendererInfo.m_Reslicer->SetOutputDimensionality( 3 ); - - rendererInfo.m_PixelsPerMM[0] = 1.0 / mmPerPixel[0]; - rendererInfo.m_PixelsPerMM[1] = 1.0 / mmPerPixel[1]; - - //calulate the originArray and the orientations for the reslice-filter - double originArray[3]; - itk2vtk( origin, originArray ); - - rendererInfo.m_Reslicer->SetResliceAxesOrigin( originArray ); - - double cosines[9]; - - // direction of the X-axis of the sampled result - vnl2vtk( right.Get_vnl_vector(), cosines ); - - // direction of the Y-axis of the sampled result - vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 ); - - // normal of the plane - vnl2vtk( normal.Get_vnl_vector(), cosines + 6 ); - - rendererInfo.m_Reslicer->SetResliceAxesDirectionCosines( cosines ); - - int xMin, xMax, yMin, yMax; - if ( boundsInitialized ) - { - // Calculate output extent (integer values) - xMin = static_cast< int >( bounds[0] / mmPerPixel[0] + 0.5 ); - xMax = static_cast< int >( bounds[1] / mmPerPixel[0] + 0.5 ); - yMin = static_cast< int >( bounds[2] / mmPerPixel[1] + 0.5 ); - yMax = static_cast< int >( bounds[3] / mmPerPixel[1] + 0.5 ); - - // Calculate the extent by which the maximal plane (due to plane rotation) - // overlaps the regular plane size. - rendererInfo.m_Overlap[0] = -xMin; - rendererInfo.m_Overlap[1] = -yMin; - } - else - { - // If no reference geometry is available, we also don't know about the - // maximum plane size; so the overlap is just ignored - rendererInfo.m_Overlap.Fill( 0.0 ); - - xMin = yMin = 0; - xMax = static_cast< int >( rendererInfo.m_Extent[0] - - rendererInfo.m_PixelsPerMM[0] + 0.5 ); - yMax = static_cast< int >( rendererInfo.m_Extent[1] - - rendererInfo.m_PixelsPerMM[1] + 0.5 ); - } - - - // Disallow huge dimensions - if ( (xMax-xMin) * (yMax-yMin) > 4096*4096 ) - { - return; - } - - - // Calculate dataset spacing in plane z direction (NOT spacing of current - // world geometry) - - double dataZSpacing = 1.0; - - normal.Normalize(); - Vector3D normInIndex; - inputGeometry->WorldToIndex( normal, normInIndex ); - - if(thickSlicesMode > 0) - { - dataZSpacing = 1.0 / normInIndex.GetNorm(); - rendererInfo.m_Reslicer->SetOutputDimensionality( 3 ); - rendererInfo.m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, -thickSlicesNum, 0+thickSlicesNum ); - } - else - { - rendererInfo.m_Reslicer->SetOutputDimensionality( 2 ); - rendererInfo.m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 0 ); - } - - rendererInfo.m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); - rendererInfo.m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], dataZSpacing ); - - // xMax and yMax are meant exclusive until now, whereas - // SetOutputExtent wants an inclusive bound. Thus, we need - // to subtract 1. - - // Do the reslicing. Modified() is called to make sure that the reslicer is - // executed even though the input geometry information did not change; this - // is necessary when the input /em data, but not the /em geometry changes. - - // The reslicing result is used both for 2D and for 3D mapping. 2D mapping - // currently uses PIC data structures, while 3D mapping uses VTK data. Thus, - // the reslicing result needs to be stored twice. - - // 1. Check the result - vtkImageData* reslicedImage = 0; - - if(thickSlicesMode>0) - { - rendererInfo.m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); - rendererInfo.m_TSFilter->SetInput( rendererInfo.m_Reslicer->GetOutput() ); - rendererInfo.m_TSFilter->Modified(); - rendererInfo.m_TSFilter->Update(); - reslicedImage = rendererInfo.m_TSFilter->GetOutput(); - } - else - { - rendererInfo.m_Reslicer->Modified(); - rendererInfo.m_Reslicer->Update(); - reslicedImage = rendererInfo.m_Reslicer->GetOutput(); - } - - if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) - { - MITK_WARN << "reslicer returned empty image"; - return; - } - - - // 2. Convert the resampling result to PIC image format - mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage ); - - if (pic == NULL) - { - return; - } - - bool imageIs2D = true; - - if ( pic->dim == 1 ) - { - pic->dim = 2; - pic->n[1] = 1; - imageIs2D = false; - } - assert( pic->dim == 2 ); - - rendererInfo.m_Pic = pic; - - if ( pic->bpe == 24 && reslicedImage->GetScalarType()==VTK_UNSIGNED_CHAR ) // RGB image - m_iil4mitkMode = iil4mitkImage::RGB; - else if ( pic->bpe == 32 && reslicedImage->GetScalarType()==VTK_UNSIGNED_CHAR ) // RGBA image - m_iil4mitkMode = iil4mitkImage::RGBA; - - image->setPicImage( pic, m_iil4mitkMode ); - image->setInterpolation( false ); - image->setRegion( 0, 0, pic->n[0], pic->n[1] ); - - - // 3. Store the result in a VTK image - if ( imageIs2D ) - { - if ( rendererInfo.m_Image == NULL ) - { - rendererInfo.m_Image = vtkImageData::New();//reslicedImage; - } - rendererInfo.m_Image->DeepCopy( reslicedImage ); - rendererInfo.m_Image->Update(); - } - else - { - if ( rendererInfo.m_Image != NULL ) - { - rendererInfo.m_Image->Delete(); - } - rendererInfo.m_Image = NULL; - } - - // We have been modified - rendererInfo.m_LastUpdateTime.Modified(); -} - - -double -mitk::ImageMapperGL2D::CalculateSpacing( const mitk::Geometry3D *geometry, const mitk::Vector3D &d ) const -{ - // The following can be derived from the ellipsoid equation - // - // 1 = x^2/a^2 + y^2/b^2 + z^2/c^2 - // - // where (a,b,c) = spacing of original volume (ellipsoid radii) - // and (x,y,z) = scaled coordinates of vector d (according to ellipsoid) - // - const mitk::Vector3D &spacing = geometry->GetSpacing(); - - double scaling = d[0]*d[0] / (spacing[0] * spacing[0]) - + d[1]*d[1] / (spacing[1] * spacing[1]) - + d[2]*d[2] / (spacing[2] * spacing[2]); - - scaling = sqrt( scaling ); - - return ( sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ) / scaling ); -} - -bool -mitk::ImageMapperGL2D -::LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ) -{ - vtkFloatingPointType point1[3]; - vtkFloatingPointType point2[3]; - points->GetPoint( p1, point1 ); - points->GetPoint( p2, point2 ); - - if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) - { - double x, y; - x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); - y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); - - if ( x < bounds[0] ) { bounds[0] = x; } - if ( x > bounds[1] ) { bounds[1] = x; } - if ( y < bounds[2] ) { bounds[2] = y; } - if ( y > bounds[3] ) { bounds[3] = y; } - bounds[4] = bounds[5] = 0.0; - return true; - } - return false; -} - - -bool -mitk::ImageMapperGL2D -::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) -{ - // Clip the plane with the bounding geometry. To do so, the corner points - // of the bounding box are transformed by the inverse transformation - // matrix, and the transformed bounding box edges derived therefrom are - // clipped with the plane z=0. The resulting min/max values are taken as - // bounds for the image reslicer. - const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); - - mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); - mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); - mitk::BoundingBox::PointType bbCenter = boundingBox->GetCenter(); - - vtkPoints *points = vtkPoints::New(); - if(boundingGeometry->GetImageGeometry()) - { - points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); - points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); - points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); - } - else - { - points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); - points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); - points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); - points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); - points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); - points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); - points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); - points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); - } - - vtkPoints *newPoints = vtkPoints::New(); - - vtkTransform *transform = vtkTransform::New(); - transform->Identity(); - transform->Concatenate( - planeGeometry->GetVtkTransform()->GetLinearInverse() - ); - - transform->Concatenate( boundingGeometry->GetVtkTransform() ); - - transform->TransformPoints( points, newPoints ); - - bounds[0] = bounds[2] = 10000000.0; - bounds[1] = bounds[3] = -10000000.0; - bounds[4] = bounds[5] = 0.0; - - this->LineIntersectZero( newPoints, 0, 1, bounds ); - this->LineIntersectZero( newPoints, 1, 2, bounds ); - this->LineIntersectZero( newPoints, 2, 3, bounds ); - this->LineIntersectZero( newPoints, 3, 0, bounds ); - this->LineIntersectZero( newPoints, 0, 4, bounds ); - this->LineIntersectZero( newPoints, 1, 5, bounds ); - this->LineIntersectZero( newPoints, 2, 6, bounds ); - this->LineIntersectZero( newPoints, 3, 7, bounds ); - this->LineIntersectZero( newPoints, 4, 5, bounds ); - this->LineIntersectZero( newPoints, 5, 6, bounds ); - this->LineIntersectZero( newPoints, 6, 7, bounds ); - this->LineIntersectZero( newPoints, 7, 4, bounds ); - - // clean up vtk data - points->Delete(); - newPoints->Delete(); - transform->Delete(); - - if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) - || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) - { - return false; - } - else - { - // The resulting bounds must be adjusted by the plane spacing, since we - // we have so far dealt with index coordinates - const float *planeSpacing = planeGeometry->GetFloatSpacing(); - bounds[0] *= planeSpacing[0]; - bounds[1] *= planeSpacing[0]; - bounds[2] *= planeSpacing[1]; - bounds[3] *= planeSpacing[1]; - bounds[4] *= planeSpacing[2]; - bounds[5] *= planeSpacing[2]; - return true; - } -} - - - -void -mitk::ImageMapperGL2D::GenerateAllData() -{ - RendererInfoMap::iterator it, end = m_RendererInfo.end(); - - for ( it = m_RendererInfo.begin(); it != end; ++it) - { - this->Update( it->first ); - } -} - - -void -mitk::ImageMapperGL2D::Clear() -{ - RendererInfoMap::iterator it, end = m_RendererInfo.end(); - for ( it = m_RendererInfo.begin(); it != end; ++it ) - { - it->second.RemoveObserver(); - it->second.Squeeze(); - } - m_RendererInfo.clear(); -} - - -void -mitk::ImageMapperGL2D::ApplyProperties(mitk::BaseRenderer* renderer) -{ - RendererInfo &rendererInfo = this->AccessRendererInfo( renderer ); - iil4mitkPicImage *image = rendererInfo.Get_iil4mitkImage(); - - assert( image != NULL ); - - float rgba[4]= { 1.0f, 1.0f, 1.0f, 1.0f }; - float opacity = 1.0f; - - // check for color prop and use it for rendering if it exists - // binary image hovering & binary image selection - bool hover = false; - bool selected = false; - GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); - GetDataNode()->GetBoolProperty("selected", selected, renderer); - if(hover && !selected) - { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.hoveringcolor", renderer)); - if(colorprop.IsNotNull()) - memcpy(rgba, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); - else - GetColor( rgba, renderer ); - - } - if(selected) - { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.selectedcolor", renderer)); - if(colorprop.IsNotNull()) - memcpy(rgba, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); - else - GetColor( rgba, renderer ); - - } - if(!hover && !selected) - { - GetColor( rgba, renderer ); - } - - // check for opacity prop and use it for rendering if it exists - GetOpacity( opacity, renderer ); - rgba[3] = opacity; - - // check for interpolation properties - bool textureInterpolation = false; - GetDataNode()->GetBoolProperty( - "texture interpolation", textureInterpolation, renderer - ); - - rendererInfo.m_TextureInterpolation = textureInterpolation; - - mitk::LevelWindow levelWindow; - mitk::LevelWindow opacLevelWindow; - - bool binary = false; - this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); - - if ( binary ) - { - - image->setExtrema(0, 1); - image->setOpacityExtrema( 0.0, 255.0 ); - image->setBinary(true); - - bool binaryOutline = false; - if ( this->GetInput()->GetPixelType().GetBpe() <= 8 ) - { - if (this->GetDataNode()->GetBoolProperty( "outline binary", binaryOutline, renderer )) - { - image->setOutline(binaryOutline); - float binaryOutlineWidth(1.0); - if (this->GetDataNode()->GetFloatProperty( "outline width", binaryOutlineWidth, renderer )) - { - image->setOutlineWidth(binaryOutlineWidth); - } - } - } - else - { - //this->GetDataNode()->SetBoolProperty( "outline binary", false, renderer ); - //this->GetDataNode()->SetFloatProperty( "opacity", 0.3, renderer ); - //set opacity - //rgba[3] = 0.3; - MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; - } - } - else - { - if( !this->GetLevelWindow( levelWindow, renderer, "levelWindow" ) ) - { - this->GetLevelWindow( levelWindow, renderer ); - } - - image->setExtrema( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); - - // obtain opacity level window - if( this->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) - { - image->setOpacityExtrema( opacLevelWindow.GetLowerWindowBound(), opacLevelWindow.GetUpperWindowBound() ); - } - else - { - image->setOpacityExtrema( 0.0, 255.0 ); - } - } - - bool useColor = false; - GetDataNode()->GetBoolProperty( "use color", useColor, renderer ); - mitk::LookupTableProperty::Pointer LookupTableProp; - - if ( !useColor ) - { - LookupTableProp = dynamic_cast( - this->GetDataNode()->GetProperty("LookupTable")); - - if ( LookupTableProp.IsNull() ) - { - useColor = true; - } - } - - if ( useColor || binary ) - { - // If lookup table use is NOT requested (or we have a binary image...): - m_iil4mitkMode = iil4mitkImage::INTENSITY_ALPHA; - image->setColor( rgba[0], rgba[1], rgba[2], rgba[3] ); - } - else - { - // If lookup table use is requested: - m_iil4mitkMode = iil4mitkImage::COLOR_ALPHA; - // only update the lut, when the properties have changed... - if ( LookupTableProp->GetLookupTable()->GetMTime() - <= this->GetDataNode()->GetPropertyList()->GetMTime() ) - { - LookupTableProp->GetLookupTable()->ChangeOpacityForAll( opacity ); - LookupTableProp->GetLookupTable()->ChangeOpacity(0, 0.0); - } - image->setColors(LookupTableProp->GetLookupTable()->GetRawLookupTable()); - } -} - -void -mitk::ImageMapperGL2D::Update(mitk::BaseRenderer* renderer) -{ - mitk::Image* data = const_cast( - this->GetInput() - ); - - if ( data == NULL ) - { - return; - } - - if ( !IsVisible(renderer) ) - { - return; - } - - // Calculate time step of the input data for the specified renderer (integer value) - this->CalculateTimeStep( renderer ); - - // Check if time step is valid - const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); - if ( ( dataTimeGeometry == NULL ) - || ( dataTimeGeometry->GetTimeSteps() == 0 ) - || ( !dataTimeGeometry->IsValidTime( this->GetTimestep() ) ) ) - { - return; - } - - - const DataNode *node = this->GetDataNode(); - - RendererInfo& rendererInfo = AccessRendererInfo( renderer ); - iil4mitkPicImage* image = rendererInfo.Get_iil4mitkImage(); - - data->UpdateOutputInformation(); - - if ( (image == NULL) - || (rendererInfo.m_LastUpdateTime < node->GetMTime()) - || (rendererInfo.m_LastUpdateTime < data->GetPipelineMTime()) - || (rendererInfo.m_LastUpdateTime - < renderer->GetCurrentWorldGeometry2DUpdateTime()) - || (rendererInfo.m_LastUpdateTime - < renderer->GetDisplayGeometryUpdateTime()) ) - { - this->GenerateDataForRenderer( renderer ); - } - else if ( rendererInfo.m_LastUpdateTime - < renderer->GetCurrentWorldGeometry2D()->GetMTime() ) - { - this->GenerateDataForRenderer( renderer ); - } - else if ( (rendererInfo.m_LastUpdateTime < node->GetPropertyList()->GetMTime()) - || (rendererInfo.m_LastUpdateTime - < node->GetPropertyList(renderer)->GetMTime()) ) - { - this->GenerateDataForRenderer( renderer ); - - // since we have checked that nothing important has changed, we can set - // m_LastUpdateTime to the current time - rendererInfo.m_LastUpdateTime.Modified(); - } -} - - -void -mitk::ImageMapperGL2D -::DeleteRendererCallback( itk::Object *object, const itk::EventObject & ) -{ - mitk::BaseRenderer *renderer = dynamic_cast< mitk::BaseRenderer* >( object ); - if ( renderer ) - { - m_RendererInfo.erase( renderer ); - } -} - - -mitk::ImageMapperGL2D::RendererInfo -::RendererInfo() -: m_RendererID(-1), -m_iil4mitkImage(NULL), -m_Renderer(NULL), -m_Pic(NULL), -m_UnitSpacingImageFilter( NULL ), -m_Reslicer( NULL ), -m_TSFilter( NULL ), -m_Image(NULL), -m_ReferenceGeometry(NULL), -m_TextureInterpolation(true), -m_ObserverID( 0 ) -{ - m_PixelsPerMM.Fill(0); -}; - - -mitk::ImageMapperGL2D::RendererInfo -::~RendererInfo() -{ - this->Squeeze(); - - if ( m_UnitSpacingImageFilter != NULL ) - { - m_UnitSpacingImageFilter->Delete(); - } - if ( m_Reslicer != NULL ) - { - m_Reslicer->Delete(); - } - if ( m_TSFilter != NULL ) - { - m_TSFilter->Delete(); - } - if ( m_Image != NULL ) - { - m_Image->Delete(); - } -} - - -void -mitk::ImageMapperGL2D::RendererInfo -::Set_iil4mitkImage( iil4mitkPicImage *iil4mitkImage ) -{ - assert( iil4mitkImage != NULL ); - - delete m_iil4mitkImage; - m_iil4mitkImage = iil4mitkImage; -} - -void -mitk::ImageMapperGL2D::RendererInfo::Squeeze() -{ - delete m_iil4mitkImage; - m_iil4mitkImage = NULL; - if ( m_Pic != NULL ) - { - mitkIpPicFree(m_Pic); - m_Pic = NULL; - } - if ( m_Image != NULL ) - { - m_Image->Delete(); - m_Image = NULL; - } -} - -void -mitk::ImageMapperGL2D::RendererInfo::RemoveObserver() -{ - if ( m_ObserverID != 0 ) - { - // m_ObserverID has to be decreased by one. Was incremented by one after creation to make the test m_ObserverID != 0 possible. - m_Renderer->RemoveObserver( m_ObserverID-1 ); - } -} - - -void mitk::ImageMapperGL2D::RendererInfo::Initialize( int rendererID, mitk::BaseRenderer *renderer, - unsigned long observerID ) -{ - // increase ID by one to avoid 0 ID, has to be decreased before remove of the observer - m_ObserverID = observerID+1; - - assert(rendererID>=0); - assert(m_RendererID<0); - - m_RendererID = rendererID; - m_Renderer = renderer; - - m_Image = vtkImageData::New(); - - m_Reslicer = vtkImageReslice::New(); - m_TSFilter = vtkMitkThickSlicesFilter::New(); - - m_Reslicer->ReleaseDataFlagOn(); - m_TSFilter->ReleaseDataFlagOn(); - - m_UnitSpacingImageFilter = vtkImageChangeInformation::New(); - m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); -} - -void mitk::ImageMapperGL2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) -{ - mitk::Image::Pointer image = dynamic_cast(node->GetData()); - - // Properties common for both images and segmentations - node->AddProperty( "use color", mitk::BoolProperty::New( true ), renderer, overwrite ); - node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); - node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); - if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); - else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); - node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) - node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); - node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); - - bool isBinaryImage(false); - if ( ! node->GetBoolProperty("binary", isBinaryImage) ) - { - - // ok, property is not set, use heuristic to determine if this - // is a binary image - mitk::Image::Pointer centralSliceImage; - ScalarType minValue = 0.0; - ScalarType maxValue = 0.0; - ScalarType min2ndValue = 0.0; - ScalarType max2ndValue = 0.0; - mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); - - sliceSelector->SetInput(image); - sliceSelector->SetSliceNr(image->GetDimension(2)/2); - sliceSelector->SetTimeNr(image->GetDimension(3)/2); - sliceSelector->SetChannelNr(image->GetDimension(4)/2); - sliceSelector->Update(); - centralSliceImage = sliceSelector->GetOutput(); - if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) - { - minValue = centralSliceImage->GetScalarValueMin(); - maxValue = centralSliceImage->GetScalarValueMax(); - min2ndValue = centralSliceImage->GetScalarValue2ndMin(); - max2ndValue = centralSliceImage->GetScalarValue2ndMax(); - } - if ( minValue == maxValue ) - { - // centralSlice is strange, lets look at all data - minValue = image->GetScalarValueMin(); - maxValue = image->GetScalarValueMaxNoRecompute(); - min2ndValue = image->GetScalarValue2ndMinNoRecompute(); - max2ndValue = image->GetScalarValue2ndMaxNoRecompute(); - } - isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); - } - - // some more properties specific for a binary... - if (isBinaryImage) - { - node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); - node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); - node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); - } - else //...or image type object - { - node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); - node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); - node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); - node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); - } - - if(image.IsNotNull() && image->IsInitialized()) - { - if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) - { - mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); - mitk::LevelWindow levelwindow; - levelwindow.SetAuto( image, true, true ); - levWinProp->SetLevelWindow( levelwindow ); - node->SetProperty( "levelwindow", levWinProp, renderer ); - } - if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) - && (image->GetPixelType().GetItkTypeId() && *(image->GetPixelType().GetItkTypeId()) == typeid(itk::RGBAPixel))) - { - mitk::LevelWindow opaclevwin; - opaclevwin.SetRangeMinMax(0,255); - opaclevwin.SetWindowBounds(0,255); - mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); - node->SetProperty( "opaclevelwindow", prop, renderer ); - } - if((overwrite) || (node->GetProperty("LookupTable", renderer)==NULL)) - { - // add a default rainbow lookup table for color mapping - mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); - vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); - vtkLut->SetHueRange(0.6667, 0.0); - vtkLut->SetTableRange(0.0, 20.0); - vtkLut->Build(); - mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); - mitkLutProp->SetLookupTable(mitkLut); - node->SetProperty( "LookupTable", mitkLutProp ); - } - } - - Superclass::SetDefaultProperties(node, renderer, overwrite); -} - diff --git a/Core/Code/Rendering/mitkImageMapperGL2D.h b/Core/Code/Rendering/mitkImageMapperGL2D.h deleted file mode 100644 index 20a79905df..0000000000 --- a/Core/Code/Rendering/mitkImageMapperGL2D.h +++ /dev/null @@ -1,300 +0,0 @@ -/*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date$ -Version: $Revision$ - -Copyright (c) German Cancer Research Center, Division of Medical and -Biological Informatics. All rights reserved. -See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. - -=========================================================================*/ - - -#ifndef MITKIMAGEMAPPER2D_H_HEADER_INCLUDED_C10E906E -#define MITKIMAGEMAPPER2D_H_HEADER_INCLUDED_C10E906E - -#include -#include "mitkGLMapper2D.h" -#include "mitkBaseRenderer.h" - -#include -#include - -#include -#pragma GCC visibility push(default) -#include -#pragma GCC visibility pop - -#include - - -class iil4mitkPicImage; -class Vtk2itk; -class vtkImageReslice; -class vtkLookupTable; -class vtkGeneralTransform; -class vtkImageChangeInformation; -class vtkPoints; -class vtkMitkThickSlicesFilter; - -namespace mitk { - - - -/** \brief Mapper to resample and display 2D slices of a 3D image. - * - * Currently implemented for mapping on PlaneGeometry and - * AbstractTransformGeometry. The resulting 2D image (by reslicing the - * underlying 3D input image appropriately) can either be directly rendered - * in a 2D view or just be calculated to be used later on by another - * rendering entity, e.g. in texture mapping in a 3D view. - * - * This results in a flipped version when used for texture mapping. Furthermore, - * not the complete rectangular area described by the Geometry2D from the renderer - * is resampled, @em if the Geometry2D is larger than the image dimension in the - * requested direction. This results in a stretched version when used for texture - * mapping. - * - - * Properties that can be set for images and influence the imageMapper2D are: - * - * - \b "modality": (mitkModalityProperty) Modality of the image - * - \b "opacity": (FloatProperty) Opacity of the image - * - \b "color": (ColorProperty) Color of the image - * - \b "use color": (BoolProperty) Use the color of the image or not - * - \b "binary": (BoolProperty) is the image a binary image or not - * - \b "outline binary": (BoolProperty) show outline of the image or not - * - \b "texture interpolation": (BoolProperty) texture interpolation of the image - * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image - * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not - * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not - * - \b "layer": (IntProperty) Layer of the image - * - \b "volume annotation color": (ColorProperty) color of the volume annotation - * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) - unit is ml/cm3 - - * The default properties are: - - * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) - * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) - * - \b "use color", mitk::BoolProperty::New( true ), renderer, overwrite ) - * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) - * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) - * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) - * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) - * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) - * - \b "bounding box", mitk::BoolProperty::New( false ) ) - * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) - - * If the modality-property is set for an image, the mapper uses modality-specific default properties, - * e.g. color maps, if they are defined. - - * \ingroup Mapper - */ -class MITK_CORE_EXPORT ImageMapperGL2D : public GLMapper2D -{ - -public: - - /** Standard class typedefs. */ - mitkClassMacro( ImageMapperGL2D,GLMapper2D ); - - /** Method for creation through the object factory. */ - itkNewMacro(Self); - - /** Some convenient typedefs. */ - typedef mitk::Image InputImageType; - typedef InputImageType::Pointer InputImagePointer; - typedef InputImageType::ConstPointer InputImageConstPointer; - typedef SlicedData::RegionType InputImageRegionType; - - /** \brief Get the Image to map */ - const InputImageType *GetInput(void); - - /** \brief Calls Update() for all associated renderers. */ - virtual void GenerateAllData(); - - /** \brief Renders the (priorly) resampled image onto the screen. */ - virtual void Paint( mitk::BaseRenderer *renderer ); - - /** \brief Checks whether this mapper needs to update itself and generate - * data. */ - virtual void Update(mitk::BaseRenderer * renderer); - - virtual void ApplyProperties(mitk::BaseRenderer* renderer); - - /** \brief Internal storage class for data needed for rendering into a - * renderer - */ - class MITK_CORE_EXPORT RendererInfo - { - /** \brief internal id of the renderer the data is stored for */ - int m_RendererID; - - /** \brief stored iil4mitkPicImage containing the texture to display for - * 2D rendering (cf. m_Image) */ - iil4mitkPicImage* m_iil4mitkImage; - mitk::BaseRenderer* m_Renderer; - - public: - /** \brief timestamp of last update of stored data */ - itk::TimeStamp m_LastUpdateTime; - - /** \brief stored data as a mitkIpPicDescriptor */ - mitkIpPicDescriptor *m_Pic; - - /** \brief number of pixels per mm in x- and y-direction of the resampled */ - Vector2D m_PixelsPerMM; - - /** \brief Extent (in pixels) of the image */ - Vector2D m_Extent; - - /** \brief Overlap (in pixels) to ensure coverage of rotated images also */ - Vector2D m_Overlap; - - /** \brief Using unit spacing for resampling makes life easier */ - vtkImageChangeInformation *m_UnitSpacingImageFilter; - - /** \brief The actual reslicer (one per renderer) */ - vtkImageReslice *m_Reslicer; - - /** \brief Thickslices post filtering */ - vtkMitkThickSlicesFilter *m_TSFilter; - - /** \brief Extracted image for 3D rendering (cf. m_iil4mitkImage) */ - vtkImageData *m_Image; - - /** \brief Reference geometry associated with the world geometry */ - const Geometry3D *m_ReferenceGeometry; - - bool m_TextureInterpolation; - - /** \brief stores the id of the observer for delete event of renderer */ - unsigned long m_ObserverID; - - RendererInfo(); - - ~RendererInfo(); - - inline bool IsInitialized() const - { - return m_RendererID >= 0; - } - - void Initialize( int rendererID, mitk::BaseRenderer *renderer, - unsigned long observerID ); - - void Set_iil4mitkImage(iil4mitkPicImage* iil4mitkImage); - - inline iil4mitkPicImage* Get_iil4mitkImage() const - { - return m_iil4mitkImage; - } - - inline int GetRendererID() const - { - return m_RendererID; - } - - void RemoveObserver(); - - void Squeeze(); - }; // RendererInfo - - - - /** \brief Get the internal id of the renderer - * \sa RendererInfo - */ - virtual int GetAssociatedChannelNr( mitk::BaseRenderer *renderer ); - - /** \brief Get the RendererInfo for \a renderer */ - const RendererInfo *GetRendererInfo( mitk::BaseRenderer *renderer ) - { - return &this->AccessRendererInfo(renderer); - } - - /** \brief Release memory allocated for buffering */ - virtual void Clear(); - - static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); - -protected: - ImageMapperGL2D(); - - virtual ~ImageMapperGL2D(); - - /** Does the actual resampling, without rendering the image yet. */ - virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); - - /** \brief Get the RendererInfo for @a renderer */ - inline RendererInfo & AccessRendererInfo( mitk::BaseRenderer* renderer ) - { - RendererInfo& rendererInfo = m_RendererInfo[renderer]; - if(rendererInfo.IsInitialized()==false) - { - // Add observer for renderer reset events (RendererInfo will - // automatically be removed from list when a Renderer is deleted) - // - // Note: observer ID is passed to rendererInfo, which will take - // responsiblity to remove the observer upon its destruction - typedef itk::MemberCommand< ImageMapperGL2D > MemberCommandType; - MemberCommandType::Pointer deleteRendererCommand = - MemberCommandType::New(); - - deleteRendererCommand->SetCallbackFunction( - this, &ImageMapperGL2D::DeleteRendererCallback ); - - unsigned long observerID = renderer->AddObserver( - BaseRenderer::RendererResetEvent(), deleteRendererCommand ); - - // Initialize RendererInfo - rendererInfo.Initialize( ImageMapperGL2D::numRenderer++, renderer, observerID ); - } - - return rendererInfo; - } - - void DeleteRendererCallback( itk::Object *object, const itk::EventObject & ); - - - double CalculateSpacing( const mitk::Geometry3D *geometry, - const mitk::Vector3D &d ) const; - - bool LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ); - - bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); - - /** \brief Number of renderers data is stored for - * \todo General concept for keeping data for rendering required - * \todo static? - */ - static int numRenderer; - -protected: - typedef std::map RendererInfoMap; - - - /** \brief Map of instances of RendererInfo - * \sa RendererInfo - */ - RendererInfoMap m_RendererInfo; - - vtkGeneralTransform *m_ComposedResliceTransform; - -private: - int m_iil4mitkMode; - -}; - -} // namespace mitk - -#endif /* MITKIMAGEMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp new file mode 100644 index 0000000000..a2e2bcada2 --- /dev/null +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -0,0 +1,1081 @@ +/*========================================================================= +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. + +=========================================================================*/ + +//MITK +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//MITK Rendering +#include "mitkImageVtkMapper2D.h" +#include "vtkMitkThickSlicesFilter.h" +#include "vtkMitkApplyLevelWindowToRGBFilter.h" + +//VTK +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//ITK +#include + +mitk::ImageVtkMapper2D::ImageVtkMapper2D() +{ +} + +mitk::ImageVtkMapper2D::~ImageVtkMapper2D() +{ + //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event, + //in order to delete the images from the 3D RW. + this->InvokeEvent( itk::DeleteEvent() ); +} + +//set the two points defining the textured plane according to the dimension and spacing +void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]) +{ + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct + //plane size in crosshair rotation and swivel mode. + + float depth = this->CalculateLayerDepth(renderer); + + localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); + //These two points define the axes of the plane in combination with the origin. + //Point 1 is the x-axis and point 2 the y-axis. + //Each plane is transformed according to the view (transversal, coronal and saggital) afterwards. + localStorage->m_Plane->SetPoint1(planeBounds[1], planeBounds[2], depth); //P1: (xMax, yMin, depth) + localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) +} + +float mitk::ImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) +{ + //get the clipping range to check how deep into z direction we can render images + double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; + + //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined + float depth = -maxRange*0.01; // divide by 100 + int layer = 0; + GetDataNode()->GetIntProperty( "layer", layer, renderer); + //add the layer property for each image to render images with a higher layer on top of the others + depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) + if(depth > 0.0f) { + depth = 0.0f; + MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; + } + return depth; +} + +const mitk::Image* mitk::ImageVtkMapper2D::GetInput( void ) +{ + return static_cast< const mitk::Image * >( this->GetData() ); +} + +vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) +{ +// this->Update(renderer); + //return the actor corresponding to the renderer + return m_LSH.GetLocalStorage(renderer)->m_Actor; +} + +void mitk::ImageVtkMapper2D::MitkRenderOverlay(BaseRenderer* renderer) +{ + if ( this->IsVisible(renderer)==false ) + return; + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); + } +} + +void mitk::ImageVtkMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) +{ + if ( this->IsVisible( renderer )==false ) + return; + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); + } +} + +void mitk::ImageVtkMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) +{ + if ( this->IsVisible(renderer)==false ) + return; + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); + } +} + +void mitk::ImageVtkMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) +{ + if(IsVisible(renderer)==false) + return; + if ( GetVtkProp(renderer)->GetVisibility() ) + { + this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); + } +} + +void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) +{ + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + + mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); + + if ( input == NULL ) + { + return; + } + + //check if there is a valid worldGeometry + const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); + if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) + { + return; + } + + // check if there is something to display + if ( !input->IsVolumeSet( this->GetTimestep() ) ) return; + + input->Update(); + + vtkImageData* inputData = input->GetVtkImageData( this->GetTimestep() ); + if ( inputData == NULL ) + { + return; + } + + // how big the area is in physical coordinates: widthInMM x heightInMM pixels + mitk::ScalarType widthInMM, heightInMM; + + // where we want to sample + Point3D origin; + Vector3D right, bottom, normal; + + // take transform of input image into account + const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); + const Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( this->GetTimestep() ); + + //World spacing + ScalarType mmPerPixel[2]; + + // Bounds information for reslicing (only reuqired if reference geometry + // is present) + vtkFloatingPointType sliceBounds[6]; + bool boundsInitialized = false; + for ( int i = 0; i < 6; ++i ) + { + sliceBounds[i] = 0.0; + } + + //Extent (in pixels) of the image + Vector2D extent; + + // Do we have a simple PlaneGeometry? + // This is the "regular" case (e.g. slicing through an image axis-parallel or even oblique) + const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); + if ( planeGeometry != NULL ) + { + origin = planeGeometry->GetOrigin(); + right = planeGeometry->GetAxisVector( 0 ); // right = Extent of Image in mm (worldspace) + bottom = planeGeometry->GetAxisVector( 1 ); + normal = planeGeometry->GetNormal(); + + bool inPlaneResampleExtentByGeometry = false; + GetDataNode()->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); + + if ( inPlaneResampleExtentByGeometry ) + { + // Resampling grid corresponds to the current world geometry. This + // means that the spacing of the output 2D image depends on the + // currently selected world geometry, and *not* on the image itself. + extent[0] = worldGeometry->GetExtent( 0 ); + extent[1] = worldGeometry->GetExtent( 1 ); + } + else + { + // Resampling grid corresponds to the input geometry. This means that + // the spacing of the output 2D image is directly derived from the + // associated input image, regardless of the currently selected world + // geometry. + Vector3D rightInIndex, bottomInIndex; + inputGeometry->WorldToIndex( right, rightInIndex ); + inputGeometry->WorldToIndex( bottom, bottomInIndex ); + extent[0] = rightInIndex.GetNorm(); + extent[1] = bottomInIndex.GetNorm(); + } + + // Get the extent of the current world geometry and calculate resampling + // spacing therefrom. + widthInMM = worldGeometry->GetExtentInMM( 0 ); + heightInMM = worldGeometry->GetExtentInMM( 1 ); + + mmPerPixel[0] = widthInMM / extent[0]; + mmPerPixel[1] = heightInMM / extent[1]; + + right.Normalize(); + bottom.Normalize(); + normal.Normalize(); + + //transform the origin to corner based coordinates, because VTK is corner based. + origin += right * ( mmPerPixel[0] * 0.5 ); + origin += bottom * ( mmPerPixel[1] * 0.5 ); + + // Use inverse transform of the input geometry for reslicing the 3D image + localStorage->m_Reslicer->SetResliceTransform( + inputGeometry->GetVtkTransform()->GetLinearInverse() ); + + // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) + localStorage->m_Reslicer->SetBackgroundLevel( -32768 ); + + // Calculate the actual bounds of the transformed plane clipped by the + // dataset bounding box; this is required for drawing the texture at the + // correct position during 3D mapping. + boundsInitialized = this->CalculateClippedPlaneBounds( + worldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds ); + } + else + { + // Do we have an AbstractTransformGeometry? + // This is the case for AbstractTransformGeometry's (e.g. a thin-plate-spline transform) + const mitk::AbstractTransformGeometry* abstractGeometry = + dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); + + if(abstractGeometry != NULL) + { + + extent[0] = abstractGeometry->GetParametricExtent(0); + extent[1] = abstractGeometry->GetParametricExtent(1); + + widthInMM = abstractGeometry->GetParametricExtentInMM(0); + heightInMM = abstractGeometry->GetParametricExtentInMM(1); + + mmPerPixel[0] = widthInMM / extent[0]; + mmPerPixel[1] = heightInMM / extent[1]; + + origin = abstractGeometry->GetPlane()->GetOrigin(); + + right = abstractGeometry->GetPlane()->GetAxisVector(0); + right.Normalize(); + + bottom = abstractGeometry->GetPlane()->GetAxisVector(1); + bottom.Normalize(); + + normal = abstractGeometry->GetPlane()->GetNormal(); + normal.Normalize(); + + // Use a combination of the InputGeometry *and* the possible non-rigid + // AbstractTransformGeometry for reslicing the 3D Image + vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); + composedResliceTransform->Identity(); + composedResliceTransform->Concatenate( + inputGeometry->GetVtkTransform()->GetLinearInverse() ); + composedResliceTransform->Concatenate( + abstractGeometry->GetVtkAbstractTransform() + ); + + localStorage->m_Reslicer->SetResliceTransform( composedResliceTransform ); + composedResliceTransform->UnRegister( NULL ); // decrease RC + + // Set background level to BLACK instead of translucent, to avoid + // boundary artifacts (see Geometry2DDataVtkMapper3D) + localStorage->m_Reslicer->SetBackgroundLevel( -1023 ); + } + else + { + //no geometry => we can't reslice + return; + } + } + + // Make sure that the image to display has a certain minimum size. + if ( (extent[0] <= 2) && (extent[1] <= 2) ) + { + return; + } + + //### begin set reslice interpolation + // Initialize the interpolation mode for resampling; switch to nearest + // neighbor if the input image is too small. + if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) + { + VtkResliceInterpolationProperty *resliceInterpolationProperty; + this->GetDataNode()->GetProperty( + resliceInterpolationProperty, "reslice interpolation" ); + + int interpolationMode = VTK_RESLICE_NEAREST; + if ( resliceInterpolationProperty != NULL ) + { + interpolationMode = resliceInterpolationProperty->GetInterpolation(); + } + + switch ( interpolationMode ) + { + case VTK_RESLICE_NEAREST: + localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor(); + break; + case VTK_RESLICE_LINEAR: + localStorage->m_Reslicer->SetInterpolationModeToLinear(); + break; + case VTK_RESLICE_CUBIC: + localStorage->m_Reslicer->SetInterpolationModeToCubic(); + break; + } + } + else + { + localStorage->m_Reslicer->SetInterpolationModeToNearestNeighbor(); + } + //### end set reslice interpolation + + //Thickslicing + int thickSlicesMode = 0; + int thickSlicesNum = 1; + + // Thick slices parameters + if( inputData->GetNumberOfScalarComponents() == 1 ) // for now only single component are allowed + { + DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); + if(dn) + { + ResliceMethodProperty *resliceMethodEnumProperty=0; + + if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) + thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); + + IntProperty *intProperty=0; + if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) + { + thickSlicesNum = intProperty->GetValue(); + if(thickSlicesNum < 1) thickSlicesNum=1; + if(thickSlicesNum > 10) thickSlicesNum=10; + } + } + else + { + MITK_WARN << "no associated widget plane data tree node found"; + } + } + + localStorage->m_UnitSpacingImageFilter->SetInput( inputData ); + localStorage->m_Reslicer->SetInput( localStorage->m_UnitSpacingImageFilter->GetOutput() ); + + //number of pixels per mm in x- and y-direction of the resampled + Vector2D pixelsPerMM; + pixelsPerMM[0] = 1.0 / mmPerPixel[0]; + pixelsPerMM[1] = 1.0 / mmPerPixel[1]; + + //calulate the originArray and the orientations for the reslice-filter + double originArray[3]; + itk2vtk( origin, originArray ); + + localStorage->m_Reslicer->SetResliceAxesOrigin( originArray ); + + double cosines[9]; + + // direction of the X-axis of the sampled result + vnl2vtk( right.Get_vnl_vector(), cosines ); + + // direction of the Y-axis of the sampled result + vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 );//fill next 3 elements + + // normal of the plane + vnl2vtk( normal.Get_vnl_vector(), cosines + 6 );//fill the last 3 elements + + localStorage->m_Reslicer->SetResliceAxesDirectionCosines( cosines ); + + int xMin, xMax, yMin, yMax; + if ( boundsInitialized ) + { + // Calculate output extent (integer values) + xMin = static_cast< int >( sliceBounds[0] / mmPerPixel[0] + 0.5 ); + xMax = static_cast< int >( sliceBounds[1] / mmPerPixel[0] + 0.5 ); + yMin = static_cast< int >( sliceBounds[2] / mmPerPixel[1] + 0.5 ); + yMax = static_cast< int >( sliceBounds[3] / mmPerPixel[1] + 0.5 ); + } + else + { + // If no reference geometry is available, we also don't know about the + // maximum plane size; + xMin = yMin = 0; + xMax = static_cast< int >( extent[0] + - pixelsPerMM[0] + 0.5); + yMax = static_cast< int >( extent[1] + - pixelsPerMM[1] + 0.5); + } + + // Disallow huge dimensions + if ( (xMax-xMin) * (yMax-yMin) > 4096*4096 ) + { + return; + } + + // Calculate dataset spacing in plane z direction (NOT spacing of current + // world geometry) + double dataZSpacing = 1.0; + + Vector3D normInIndex; + inputGeometry->WorldToIndex( normal, normInIndex ); + + if(thickSlicesMode > 0) + { + dataZSpacing = 1.0 / normInIndex.GetNorm(); + localStorage->m_Reslicer->SetOutputDimensionality( 3 ); + localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, -thickSlicesNum, 0+thickSlicesNum ); + } + else + { + localStorage->m_Reslicer->SetOutputDimensionality( 2 ); + localStorage->m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 0 ); + } + + localStorage->m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); + localStorage->m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], dataZSpacing ); + // xMax and yMax are meant exclusive until now, whereas + // SetOutputExtent wants an inclusive bound. Thus, we need + // to subtract 1. + + vtkImageData* reslicedImage = 0; + // Do the reslicing. Modified() is called to make sure that the reslicer is + // executed even though the input geometry information did not change; this + // is necessary when the input /em data, but not the /em geometry changes. + if(thickSlicesMode>0) + { + localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); + localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetOutput() ); + localStorage->m_TSFilter->Modified(); + localStorage->m_TSFilter->Update(); + reslicedImage = localStorage->m_TSFilter->GetOutput(); + } + else + { + localStorage->m_Reslicer->Modified(); + localStorage->m_Reslicer->Update(); + reslicedImage = localStorage->m_Reslicer->GetOutput(); + } + + if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) + { + MITK_WARN << "reslicer returned empty image"; + return; + } + + //set the current slice for the localStorage +// localStorage->m_ReslicedImage = reslicedImage; + localStorage->m_ReslicedImage->DeepCopy( reslicedImage ); + + //set the current slice as texture for the plane + localStorage->m_Texture->SetInput(localStorage->m_ReslicedImage); + + //setup the textured plane + this->GeneratePlane( renderer, sliceBounds ); + + //apply the properties after the slice was set + this->ApplyProperties( renderer, mmPerPixel ); + + //get the transformation matrix of the reslicer in order to render the slice as transversal, coronal or saggital + vtkSmartPointer trans = vtkSmartPointer::New(); + vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); + + //transform the origin to center based coordinates, because MITK is center based. + Point3D originCenterBased = origin; + originCenterBased -= right * ( mmPerPixel[0] * 0.5 ); + originCenterBased -= bottom * ( mmPerPixel[1] * 0.5 ); + + matrix->SetElement(0, 3, originCenterBased[0]); + matrix->SetElement(1, 3, originCenterBased[1]); + matrix->SetElement(2, 3, originCenterBased[2]); + trans->SetMatrix(matrix); + + //transform the plane/contour (the actual actor) to the corresponding view (transversal, coronal or saggital) + localStorage->m_Actor->SetUserTransform(trans); + + // We have been modified => save this for next Update() + localStorage->m_LastUpdateTime.Modified(); +} + +bool mitk::ImageVtkMapper2D::LineIntersectZero( vtkPoints *points, int p1, int p2, + vtkFloatingPointType *bounds ) +{ + vtkFloatingPointType point1[3]; + vtkFloatingPointType point2[3]; + points->GetPoint( p1, point1 ); + points->GetPoint( p2, point2 ); + + if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) + { + double x, y; + x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); + y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); + + if ( x < bounds[0] ) { bounds[0] = x; } + if ( x > bounds[1] ) { bounds[1] = x; } + if ( y < bounds[2] ) { bounds[2] = y; } + if ( y > bounds[3] ) { bounds[3] = y; } + bounds[4] = bounds[5] = 0.0; + return true; + } + return false; +} + +bool mitk::ImageVtkMapper2D::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) +{ + // Clip the plane with the bounding geometry. To do so, the corner points + // of the bounding box are transformed by the inverse transformation + // matrix, and the transformed bounding box edges derived therefrom are + // clipped with the plane z=0. The resulting min/max values are taken as + // bounds for the image reslicer. + const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); + + mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); + mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); + + vtkSmartPointer points = vtkSmartPointer::New(); + if(boundingGeometry->GetImageGeometry()) + { + points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); + points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); + points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); + } + else + { + points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); + points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); + points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); + points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); + points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); + } + + vtkSmartPointer newPoints = vtkSmartPointer::New(); + + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->Identity(); + transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); + + transform->Concatenate( boundingGeometry->GetVtkTransform() ); + + transform->TransformPoints( points, newPoints ); + + bounds[0] = bounds[2] = 10000000.0; + bounds[1] = bounds[3] = -10000000.0; + bounds[4] = bounds[5] = 0.0; + + this->LineIntersectZero( newPoints, 0, 1, bounds ); + this->LineIntersectZero( newPoints, 1, 2, bounds ); + this->LineIntersectZero( newPoints, 2, 3, bounds ); + this->LineIntersectZero( newPoints, 3, 0, bounds ); + this->LineIntersectZero( newPoints, 0, 4, bounds ); + this->LineIntersectZero( newPoints, 1, 5, bounds ); + this->LineIntersectZero( newPoints, 2, 6, bounds ); + this->LineIntersectZero( newPoints, 3, 7, bounds ); + this->LineIntersectZero( newPoints, 4, 5, bounds ); + this->LineIntersectZero( newPoints, 5, 6, bounds ); + this->LineIntersectZero( newPoints, 6, 7, bounds ); + this->LineIntersectZero( newPoints, 7, 4, bounds ); + + if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) + || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) + { + return false; + } + else + { + // The resulting bounds must be adjusted by the plane spacing, since we + // we have so far dealt with index coordinates + const float *planeSpacing = planeGeometry->GetFloatSpacing(); + bounds[0] *= planeSpacing[0]; + bounds[1] *= planeSpacing[0]; + bounds[2] *= planeSpacing[1]; + bounds[3] *= planeSpacing[1]; + bounds[4] *= planeSpacing[2]; + bounds[5] *= planeSpacing[2]; + return true; + } +} + +void mitk::ImageVtkMapper2D::ApplyProperties(mitk::BaseRenderer* renderer, mitk::ScalarType mmPerPixel[2]) +{ + //get the current localStorage for the corresponding renderer + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + + // check for interpolation properties + bool textureInterpolation = false; + GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); + + //set the interpolation modus according to the property + localStorage->m_Texture->SetInterpolate(textureInterpolation); + + //do not repeat the texture (the image) + localStorage->m_Texture->RepeatOff(); + + float rgb[3]= { 1.0f, 1.0f, 1.0f }; + float opacity = 1.0f; + + // check for opacity prop and use it for rendering if it exists + GetOpacity( opacity, renderer ); + //set the opacity according to the properties + localStorage->m_Actor->GetProperty()->SetOpacity(opacity); + + // check for color prop and use it for rendering if it exists + // binary image hovering & binary image selection + bool hover = false; + bool selected = false; + GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); + GetDataNode()->GetBoolProperty("selected", selected, renderer); + if(hover && !selected) + { + mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty + ("binaryimage.hoveringcolor", renderer)); + if(colorprop.IsNotNull()) + { + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + } + else + { + GetColor( rgb, renderer ); + } + + } + if(selected) + { + mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty + ("binaryimage.selectedcolor", renderer)); + if(colorprop.IsNotNull()) { + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + } + else + { + GetColor( rgb, renderer ); + } + + } + if(!hover && !selected) + { + GetColor( rgb, renderer ); + } + + //get the binary property + bool binary = false; + this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); + + //use color means that we want to use the color from the property list and not a lookuptable + bool useColor = true; + this->GetDataNode()->GetBoolProperty( "use color", useColor, renderer ); + + //the finalLookuptable will be used for the rendering and can either be a user-defined table or the default lut + vtkSmartPointer finalLookuptable = localStorage->m_LookupTable; + + //BEGIN PROPERTY user-defined lut + //currently we do not allow a lookuptable if it is a binary image + bool useDefaultLut = true; + if((!useColor) && (!binary)) + { + // If lookup table use is requested... + mitk::LookupTableProperty::Pointer LookupTableProp; + LookupTableProp = dynamic_cast + (this->GetDataNode()->GetProperty("LookupTable")); + //...check if there is a lookuptable provided by the user + if ( LookupTableProp.IsNull() ) + { + MITK_WARN << "The use of a lookuptable is requested, but there is no lookuptable supplied by the user! The default lookuptable will be used instead."; + } + else + { + // If lookup table use is requested and supplied by the user: + // only update the lut, when the properties have changed... + if( LookupTableProp->GetLookupTable()->GetMTime() + <= this->GetDataNode()->GetPropertyList()->GetMTime() ) + { + LookupTableProp->GetLookupTable()->ChangeOpacityForAll( opacity ); + LookupTableProp->GetLookupTable()->ChangeOpacity(0, 0.0); + } + //we use the user-defined lookuptable + finalLookuptable = LookupTableProp->GetLookupTable()->GetVtkLookupTable(); + //we obtained a user-defined lut and dont have to use the default table + useDefaultLut = false; + } + }//END PROPERTY user-defined lut + + //use the finalLookuptable for mapping the colors + localStorage->m_Texture->SetLookupTable( finalLookuptable ); + + //check if we need the default table + if( useDefaultLut ) + { + double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK + localStorage->m_Actor->GetProperty()->SetColor(rgbConv); + } + else + { + //If the user defines a lut, we dont want to use the color and take white instead. + localStorage->m_Actor->GetProperty()->SetColor(1.0, 1.0, 1.0); + } + + bool binaryOutline = false; + this->GetDataNode()->GetBoolProperty( "outline binary", binaryOutline, renderer ); + if ( binary ) + { + finalLookuptable->SetRange(0.0, 1.0); + //0 is already mapped to transparent. + //1 is now mapped to the current color and alpha + + if ( this->GetInput()->GetPixelType().GetBpe() <= 8 ) + { + if (binaryOutline) + { + //generate ontours/outlines TODO: not always necessary + localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer ,localStorage->m_ReslicedImage, mmPerPixel); + + float binaryOutlineWidth(1.0); + if (this->GetDataNode()->GetFloatProperty( "outline width", binaryOutlineWidth, renderer )) + { + localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth); + } + } + } + else + { + MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; + } + } //END binary image handling + else + { + LevelWindow levelWindow; + this->GetLevelWindow( levelWindow, renderer ); + + //set up the lookuptable with the level window range + finalLookuptable->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); + + mitk::PixelType pixelType = this->GetInput()->GetPixelType(); + if( pixelType.GetBitsPerComponent() == pixelType.GetBpe() ) //gray images with just one component + { + localStorage->m_Texture->MapColorScalarsThroughLookupTableOn(); + } + else //RGB, RBGA or other images tpyes with more components + { + // obtain and apply opacity level window if possible + localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); + localStorage->m_LevelWindowToRGBFilterObject->SetLookupTable(localStorage->m_Texture->GetLookupTable()); + mitk::LevelWindow opacLevelWindow; + if( this->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) + { + localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); + localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); + } + else + { + localStorage->m_LevelWindowToRGBFilterObject->SetMinOpacity(0.0); + localStorage->m_LevelWindowToRGBFilterObject->SetMaxOpacity(255.0); + } + localStorage->m_LevelWindowToRGBFilterObject->SetInput(localStorage->m_ReslicedImage); + localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowToRGBFilterObject->GetOutputPort()); + } + } + + if(binaryOutline && binary) + { + //We need the contour for the binary oultine property as actor + localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData); + localStorage->m_Actor->SetTexture(NULL); //no texture for contours + } + else + { + //set the plane as input for the mapper + localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); + //set the texture for the actor + localStorage->m_Actor->SetTexture(localStorage->m_Texture); + } +} + +void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) +{ + if ( !this->IsVisible( renderer ) ) + { + return; + } + + mitk::Image* data = const_cast( this->GetInput() ); + if ( data == NULL ) + { + return; + } + + // Calculate time step of the input data for the specified renderer (integer value) + this->CalculateTimeStep( renderer ); + + // Check if time step is valid + const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); + if ( ( dataTimeGeometry == NULL ) + || ( dataTimeGeometry->GetTimeSteps() == 0 ) + || ( !dataTimeGeometry->IsValidTime( this->GetTimestep() ) ) ) + { + return; + } + + const DataNode *node = this->GetDataNode(); + data->UpdateOutputInformation(); + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + + //check if something important has changed and we need to rerender + if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? + || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? + || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? + || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) + || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? + || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) + { + this->GenerateDataForRenderer( renderer ); + } + + // since we have checked that nothing important has changed, we can set + // m_LastUpdateTime to the current time + localStorage->m_LastUpdateTime.Modified(); +} + +void mitk::ImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +{ + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + + // Properties common for both images and segmentations + node->AddProperty( "use color", mitk::BoolProperty::New( true ), renderer, overwrite ); + node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); + node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); + node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); + if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); + else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); + node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) + node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); + node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); + + bool isBinaryImage(false); + if ( ! node->GetBoolProperty("binary", isBinaryImage) ) + { + + // ok, property is not set, use heuristic to determine if this + // is a binary image + mitk::Image::Pointer centralSliceImage; + ScalarType minValue = 0.0; + ScalarType maxValue = 0.0; + ScalarType min2ndValue = 0.0; + ScalarType max2ndValue = 0.0; + mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); + + sliceSelector->SetInput(image); + sliceSelector->SetSliceNr(image->GetDimension(2)/2); + sliceSelector->SetTimeNr(image->GetDimension(3)/2); + sliceSelector->SetChannelNr(image->GetDimension(4)/2); + sliceSelector->Update(); + centralSliceImage = sliceSelector->GetOutput(); + if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) + { + minValue = centralSliceImage->GetScalarValueMin(); + maxValue = centralSliceImage->GetScalarValueMax(); + min2ndValue = centralSliceImage->GetScalarValue2ndMin(); + max2ndValue = centralSliceImage->GetScalarValue2ndMax(); + } + if ( minValue == maxValue ) + { + // centralSlice is strange, lets look at all data + minValue = image->GetScalarValueMin(); + maxValue = image->GetScalarValueMaxNoRecompute(); + min2ndValue = image->GetScalarValue2ndMinNoRecompute(); + max2ndValue = image->GetScalarValue2ndMaxNoRecompute(); + } + isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); + } + + // some more properties specific for a binary... + if (isBinaryImage) + { + node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); + node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); + node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); + node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); + node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); + node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); + node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); + node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); + } + else //...or image type object + { + node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); + node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); + node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); + node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); + } + + if(image.IsNotNull() && image->IsInitialized()) + { + if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) + { + mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); + mitk::LevelWindow levelwindow; + levelwindow.SetAuto( image, true, true ); + levWinProp->SetLevelWindow( levelwindow ); + node->SetProperty( "levelwindow", levWinProp, renderer ); + } + if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) + && (image->GetPixelType().GetItkTypeId() && *(image->GetPixelType().GetItkTypeId()) == typeid(itk::RGBAPixel))) + { + mitk::LevelWindow opaclevwin; + opaclevwin.SetRangeMinMax(0,255); + opaclevwin.SetWindowBounds(0,255); + mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); + node->SetProperty( "opaclevelwindow", prop, renderer ); + } + if((overwrite) || (node->GetProperty("LookupTable", renderer)==NULL)) + { + // add a default rainbow lookup table for color mapping + mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); + vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); + vtkLut->SetHueRange(0.6667, 0.0); + vtkLut->SetTableRange(0.0, 20.0); + vtkLut->Build(); + mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); + mitkLutProp->SetLookupTable(mitkLut); + node->SetProperty( "LookupTable", mitkLutProp ); + } + } + Superclass::SetDefaultProperties(node, renderer, overwrite); +} + +vtkSmartPointer mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer, vtkSmartPointer binarySlice, mitk::ScalarType mmPerPixel[2]){ + int* dims = binarySlice->GetDimensions(); //dimensions of the image + int line = dims[0]; //how many pixels per line? + int x = 0; //pixel index x + int y = 0; //pixel index y + char* currentPixel; + int nn = dims[0]*dims[1]; //max pixel(n,n) + + //get the depth for each contour + float depth = CalculateLayerDepth(renderer); + + vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw + vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points + for (int ii = 0; ii(binarySlice->GetScalarPointer(x, y, 0)); + //if the current pixel value is set to something + if ((currentPixel) && (*currentPixel != 0)) { + //check in which direction a line is necessary + if (ii >= line && *(currentPixel-line) == 0) { //x direction - bottom edge of the pixel + //add the 2 points + vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], y*mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], y*mmPerPixel[1], depth); + //add the line between both points + lines->InsertNextCell(2); + lines->InsertCellPoint(p1); + lines->InsertCellPoint(p2); + } + if (ii <= nn-line && *(currentPixel+line) == 0) { //x direction - top edge of the pixel + vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], (y+1)*mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], (y+1)*mmPerPixel[1], depth); + lines->InsertNextCell(2); + lines->InsertCellPoint(p1); + lines->InsertCellPoint(p2); + } + if (ii > 1 && *(currentPixel-1) == 0) { //y direction - left edge of the pixel + vtkIdType p1 = points->InsertNextPoint(x*mmPerPixel[0], y*mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint(x*mmPerPixel[0], (y+1)*mmPerPixel[1], depth); + lines->InsertNextCell(2); + lines->InsertCellPoint(p1); + lines->InsertCellPoint(p2); + } + if (ii < nn-1 && *(currentPixel+1) == 0) { //y direction - right edge of the pixel + vtkIdType p1 = points->InsertNextPoint((x+1)*mmPerPixel[0], y*mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint((x+1)*mmPerPixel[0], (y+1)*mmPerPixel[1], depth); + lines->InsertNextCell(2); + lines->InsertCellPoint(p1); + lines->InsertCellPoint(p2); + } + } + + //reached end of line + x++; + if (x >= line) { + x = 0; + y++; + } + } + // Create a polydata to store everything in + vtkSmartPointer polyData = vtkSmartPointer::New(); + // Add the points to the dataset + polyData->SetPoints(points); + // Add the lines to the dataset + polyData->SetLines(lines); + return polyData; +} + +mitk::ImageVtkMapper2D::LocalStorage::LocalStorage() +{ + //Do as much actions as possible in here to avoid double executions. + m_Plane = vtkSmartPointer::New(); + m_Texture = vtkSmartPointer::New(); + m_LookupTable = vtkSmartPointer::New(); + m_Mapper = vtkSmartPointer::New(); + m_Actor = vtkSmartPointer::New(); + m_Reslicer = vtkSmartPointer::New(); + m_TSFilter = vtkSmartPointer::New(); + m_UnitSpacingImageFilter = vtkSmartPointer::New(); + m_OutlinePolyData = vtkSmartPointer::New(); + m_ReslicedImage = vtkSmartPointer::New(); + + //the following actions are always the same and thus can be performed + //in the constructor for each image (i.e. the image-corresponding local storage) + m_TSFilter->ReleaseDataFlagOn(); + m_Reslicer->ReleaseDataFlagOn(); + + m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); + + //built a default lookuptable + m_LookupTable->SetRampToLinear(); + m_LookupTable->SetSaturationRange( 0.0, 0.0 ); + m_LookupTable->SetHueRange( 0.0, 0.0 ); + m_LookupTable->SetValueRange( 0.0, 1.0 ); + m_LookupTable->Build(); + //map all black values to transparent + m_LookupTable->SetTableValue(0, 0.0, 0.0, 0.0, 0.0); + + //set the mapper for the actor + m_Actor->SetMapper(m_Mapper); + + //filter for RGB(A) images + m_LevelWindowToRGBFilterObject = new vtkMitkApplyLevelWindowToRGBFilter(); +} diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h new file mode 100644 index 0000000000..0ba0262799 --- /dev/null +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h @@ -0,0 +1,244 @@ +/*========================================================================= +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. + +=========================================================================*/ + +#ifndef MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E +#define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E + +//MITK +#include + +//MITK Rendering +#include "mitkBaseRenderer.h" +#include "mitkVtkMapper2D.h" + +//VTK +#include + +class vtkActor; +class vtkPolyDataMapper; +class vtkPlaneSource; +class vtkImageData; +class vtkLookupTable; +class vtkImageReslice; +class vtkImageChangeInformation; +class vtkPoints; +class vtkMitkThickSlicesFilter; +class vtkPolyData; +class vtkMitkApplyLevelWindowToRGBFilter; + +namespace mitk { + + /** \brief Mapper to resample and display 2D slices of a 3D image. + * + * The following image gives a brief overview of the mapping and the involved parts. + * + * \image html imageVtkMapper2Darchitecture.png + * + * First, the image is resliced by means of vtkImageReslice. The volume image + * serves as input to the mapper in addition to spatial placement of the slice and a few other + * properties such as thick slices. This code was already present in the old version + * (mitkImageMapperGL2D). + * + * Next, the obtained slice (m_ReslicedImage) is used to create a texture + * (m_Texture) and a plane onto which the texture is rendered (m_Plane). For + * mapping purposes, a vtkPolyDataMapper (m_Mapper) is utilized. Orthographic + * projection is applied to create the effect of a 2D image. The mapper and the + * texture are assigned to the actor (m_Actor) which is passed to the VTK rendering + * pipeline via the method GetVtkProp(). + * + * In order to transform the textured plane to the correct position in space, the + * same transformation as used for reslicing is applied to both the camera and the + * vtkActor. All important steps are explained in more detail below. The resulting + * 2D image (by reslicing the underlying 3D input image appropriately) can either + * be directly rendered in a 2D view or just be calculated to be used later by another + * rendering entity, e.g. in texture mapping in a 3D view. + * + * Properties that can be set for images and influence the imageMapper2D are: + * + * - \b "opacity": (FloatProperty) Opacity of the image + * - \b "color": (ColorProperty) Color of the image + * - \b "use color": (BoolProperty) Use the color of the image or not + * - \b "binary": (BoolProperty) is the image a binary image or not + * - \b "outline binary": (BoolProperty) show outline of the image or not + * - \b "texture interpolation": (BoolProperty) texture interpolation of the image + * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image + * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not + * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not + * - \b "layer": (IntProperty) Layer of the image + * - \b "volume annotation color": (ColorProperty) color of the volume annotation, TODO has to be reimplemented + * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) + unit is ml or cm3, TODO has to be reimplemented + + * The default properties are: + + * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) + * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) + * - \b "use color", mitk::BoolProperty::New( true ), renderer, overwrite ) + * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) + * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) + * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) + * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) + * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) + * - \b "bounding box", mitk::BoolProperty::New( false ) ) + * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) + + * If the modality-property is set for an image, the mapper uses modality-specific default properties, + * e.g. color maps, if they are defined. + + * \ingroup Mapper + */ + class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper2D + { + + public: + + /** Standard class typedefs. */ + mitkClassMacro( ImageVtkMapper2D,VtkMapper2D ); + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** \brief Get the Image to map */ + const mitk::Image *GetInput(void); + + /** \brief Checks whether this mapper needs to update itself and generate + * data. */ + virtual void Update(mitk::BaseRenderer * renderer); + + //### methods of MITK-VTK rendering pipeline + virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); + + virtual void MitkRenderOverlay(BaseRenderer* renderer); + virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); + virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); + virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); + //### end of methods of MITK-VTK rendering pipeline + + + /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ + /** + * To render transveral, coronal, and sagittal, the mapper is called three times. + * For performance reasons, the corresponding data for each view is saved in the + * internal helper class LocalStorage. This allows rendering n views with just + * 1 mitkMapper using n vtkMapper. + * */ + class MITK_CORE_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage + { + public: + /** \brief Actor of a 2D render window. */ + vtkSmartPointer m_Actor; + /** \brief Mapper of a 2D render window. */ + vtkSmartPointer m_Mapper; + /** \brief Current slice of a 2D render window. */ + vtkSmartPointer m_ReslicedImage; + /** \brief Plane on which the slice is rendered as texture. */ + vtkSmartPointer m_Plane; + /** \brief The texture which is used to render the current slice. */ + vtkSmartPointer m_Texture; + /** \brief The lookuptable for colors and level window */ + vtkSmartPointer m_LookupTable; + /** \brief The actual reslicer (one per renderer) */ + vtkSmartPointer m_Reslicer; + /** \brief Thickslices post filtering. */ + vtkSmartPointer m_TSFilter; + /** \brief Using unit spacing for resampling makes life easier TODO improve docu ...*/ + vtkSmartPointer m_UnitSpacingImageFilter; + /** \brief PolyData object containg all lines/points needed for outlining the contour. + This container is used to save a computed contour for the next rendering execution. + For instance, if you zoom or pann, there is no need to recompute the contour. */ + vtkSmartPointer m_OutlinePolyData; + + /** \brief Timestamp of last update of stored data. */ + itk::TimeStamp m_LastUpdateTime; + + /** \brief This filter is used to apply the level window to RBG(A) images. */ + vtkMitkApplyLevelWindowToRGBFilter* m_LevelWindowToRGBFilterObject; + + /** \brief Default constructor of the local storage. */ + LocalStorage(); + /** \brief Default deconstructor of the local storage. */ + ~LocalStorage() + { + } + }; + + /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ + mitk::Mapper::LocalStorageHandler m_LSH; + + /** \brief Set the default properties for general image rendering. */ + static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); + + protected: + /** \brief Apply all properties to the vtkActor (e.g. color, opacity, binary image handling, etc.).*/ + virtual void ApplyProperties(mitk::BaseRenderer* renderer, ScalarType mmPerPixel[2]); + + /** \brief Generates a plane according to the size of the resliced image in milimeters. + * + * \image html texturedPlane.png + * + * In VTK a vtkPlaneSource is defined through three points. The origin and two + * points defining the axes of the plane (see VTK documentation). The origin is + * set to (xMin; yMin; Z), where xMin and yMin are the minimal bounds of the + * resliced image in space. Z is relevant for blending and the layer property. + * The center of the plane (C) is also the center of the view plane (cf. the image above). + * + * \note For the standard MITK view with three 2D render windows showing three + * different slices, three such planes are generated. All these planes are generated + * in the XY-plane (even if they depict a YZ-slice of the volume). + * + */ + void GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]); + + /** \brief Generates a vtkPolyData object containing the outline of a given binary slice. + \param binarySlice - The binary image slice. (Volumes are not supported.) + \param mmPerPixel - Spacing of the binary image slice. Hence it's 2D, only in x/y-direction. + \note This code has been taken from the deprecated library iil. + */ + vtkSmartPointer CreateOutlinePolyData(mitk::BaseRenderer* renderer, vtkSmartPointer binarySlice, ScalarType mmPerPixel[2]); + + /** Default constructor */ + ImageVtkMapper2D(); + /** Default deconstructor */ + virtual ~ImageVtkMapper2D(); + + /** \brief Does the actual resampling, without rendering the image yet. + * All the data is generated inside this method. The vtkProp (or Actor) + * is filled with content (i.e. the resliced image). + * + * After generation, a 4x4 transformation matrix(t) of the current slice is obtained + * from the vtkResliceImage object via GetReslicesAxis(). This matrix is + * applied to each textured plane (actor->SetUserTransform(t)) to transform everything + * to the actual 3D position (cf. the following image). + * + * \image html cameraPositioning3D.png + * + */ + virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); + + /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ + bool LineIntersectZero( vtkPoints *points, int p1, int p2, + vtkFloatingPointType *bounds ); + + /** \brief Calculate the bounding box of the resliced image. This is necessary for + arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) + will have a new bounding box, which needs to be calculated. */ + bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, + const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); + + /** \brief This method uses the vtkCamera clipping range and the layer property + * to calcualte the depth of the object (e.g. image or contour). The depth is used + * to keep the correct order for the final VTK rendering.*/ + float CalculateLayerDepth(mitk::BaseRenderer* renderer); + }; + +} // namespace mitk + +#endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp old mode 100755 new mode 100644 diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.h b/Core/Code/Rendering/mitkPointSetGLMapper2D.h old mode 100755 new mode 100644 diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp b/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp old mode 100755 new mode 100644 diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper3D.h b/Core/Code/Rendering/mitkPointSetVtkMapper3D.h old mode 100755 new mode 100644 diff --git a/Core/Code/Rendering/mitkVtkMapper2D.h b/Core/Code/Rendering/mitkVtkMapper2D.h index 5851d57efb..d312d9a95b 100644 --- a/Core/Code/Rendering/mitkVtkMapper2D.h +++ b/Core/Code/Rendering/mitkVtkMapper2D.h @@ -1,56 +1,56 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef BASEVTKMAPPER2D_H_HEADER_INCLUDED #define BASEVTKMAPPER2D_H_HEADER_INCLUDED #include "mitkMapper2D.h" class vtkProp; namespace mitk { //##Documentation //## @brief Base class of all vtk-based 2D-Mappers //## //## Those must implement the abstract //## method vtkProp* GetProp(). //## @ingroup Mapper class MITK_CORE_EXPORT VtkMapper2D : public Mapper2D { public: mitkClassMacro(VtkMapper2D,Mapper2D); - virtual vtkProp* GetProp(mitk::BaseRenderer* renderer) = 0; + virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) = 0; /** * \brief Returns whether this is an vtk-based mapper */ virtual bool IsVtkBased() const { return true; } protected: VtkMapper2D(); virtual ~VtkMapper2D(); }; } // namespace mitk #endif /* BASEVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.cpp b/Core/Code/Rendering/mitkVtkPropRenderer.cpp index 9948927fe7..6463c99264 100644 --- a/Core/Code/Rendering/mitkVtkPropRenderer.cpp +++ b/Core/Code/Rendering/mitkVtkPropRenderer.cpp @@ -1,794 +1,918 @@ /*========================================================================= - -Program: Medical Imaging & Interaction Toolkit -Language: C++ -Date: $Date: 2007-09-22 11:55:20 +0200 (Sa, 22 Sep 2007) $ -Version: $Revision: 12240 $ - Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. - + =========================================================================*/ #include "mitkVtkPropRenderer.h" -#include "picimage.h" - // MAPPERS #include "mitkMapper.h" -#include "mitkImageMapperGL2D.h" +#include "mitkImageVtkMapper2D.h" #include "mitkVtkMapper2D.h" #include "mitkVtkMapper3D.h" #include "mitkGeometry2DDataVtkMapper3D.h" #include "mitkPointSetGLMapper2D.h" #include "mitkImageSliceSelector.h" #include "mitkRenderingManager.h" #include "mitkGL.h" #include "mitkGeometry3D.h" #include "mitkDisplayGeometry.h" #include "mitkLevelWindow.h" #include "mitkCameraController.h" #include "mitkVtkInteractorCameraController.h" #include "mitkPlaneGeometry.h" #include "mitkProperties.h" #include "mitkSurface.h" #include "mitkNodePredicateDataType.h" // VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include - - +#include +#include mitk::VtkPropRenderer::VtkPropRenderer( const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm ) : BaseRenderer(name,renWin, rm), m_VtkMapperPresent(false), - m_NewRenderer(true) + m_NewRenderer(true), + m_2DCameraInitialized(false) { didCount=false; m_WorldPointPicker = vtkWorldPointPicker::New(); m_PointPicker = vtkPointPicker::New(); m_PointPicker->SetTolerance( 0.0025 ); m_CellPicker = vtkCellPicker::New(); m_CellPicker->SetTolerance( 0.0025 ); mitk::Geometry2DDataVtkMapper3D::Pointer geometryMapper = mitk::Geometry2DDataVtkMapper3D::New(); m_CurrentWorldGeometry2DMapper = geometryMapper; m_CurrentWorldGeometry2DNode->SetMapper(2, geometryMapper); m_LightKit = vtkLightKit::New(); m_LightKit->AddLightsToRenderer(m_VtkRenderer); m_PickingMode = WorldPointPicking; m_TextRenderer = vtkRenderer::New(); m_TextRenderer->SetRenderWindow(renWin); m_TextRenderer->SetInteractive(0); m_TextRenderer->SetErase(0); - } /*! \brief Destructs the VtkPropRenderer. */ mitk::VtkPropRenderer::~VtkPropRenderer() { // Workaround for GLDisplayList Bug { m_MapperID=0; checkState(); } if (m_LightKit != NULL) m_LightKit->Delete(); if (m_VtkRenderer!=NULL) { m_CameraController = NULL; m_VtkRenderer->Delete(); m_VtkRenderer = NULL; } else m_CameraController = NULL; if (m_WorldPointPicker != NULL) m_WorldPointPicker->Delete(); if (m_PointPicker != NULL) m_PointPicker->Delete(); if (m_CellPicker != NULL) m_CellPicker->Delete(); if (m_TextRenderer != NULL) m_TextRenderer->Delete(); } void mitk::VtkPropRenderer::SetDataStorage( mitk::DataStorage* storage ) { if ( storage == NULL ) return; BaseRenderer::SetDataStorage(storage); static_cast(m_CurrentWorldGeometry2DMapper.GetPointer())->SetDataStorageForTexture( m_DataStorage.GetPointer() ); - // Compute the geometry from the current data tree bounds and set it as world geometry + // Compute the geometry from the current data tree bounds and set it as world geometry this->SetWorldGeometryToDataStorageBounds(); } bool mitk::VtkPropRenderer::SetWorldGeometryToDataStorageBounds() { if ( m_DataStorage.IsNull() ) return false; //initialize world geometry mitk::TimeSlicedGeometry::Pointer geometry = m_DataStorage->ComputeVisibleBoundingGeometry3D( NULL, "includeInBoundingBox" ); if ( geometry.IsNull() ) return false; this->SetWorldGeometry(geometry); //this->GetDisplayGeometry()->SetSizeInDisplayUnits( this->m_TextRenderer->GetRenderWindow()->GetSize()[0], this->m_TextRenderer->GetRenderWindow()->GetSize()[1] ); this->GetDisplayGeometry()->Fit(); this->GetVtkRenderer()->ResetCamera(); this->Modified(); return true; } /*! \brief Called by the vtkMitkRenderProp in order to start MITK rendering process. */ int mitk::VtkPropRenderer::Render(mitk::VtkPropRenderer::RenderType type) { - // Do we have objects to render? + + // Do we have objects to render? if ( this->GetEmptyWorldGeometry()) return 0; if ( m_DataStorage.IsNull()) return 0; // Update mappers and prepare mapper queue if (type == VtkPropRenderer::Opaque) this->PrepareMapperQueue(); //go through the generated list and let the sorted mappers paint bool lastVtkBased = true; bool sthVtkBased = false; for(MappersMapType::iterator it = m_MappersMap.begin(); it != m_MappersMap.end(); it++) { Mapper * mapper = (*it).second; if((mapper->IsVtkBased() == true) ) { sthVtkBased = true; mitk::VtkMapper3D::Pointer vtkMapper = dynamic_cast(mapper); if(vtkMapper) { - vtkMapper->GetVtkProp(this)->SetAllocatedRenderTime(5000,GetVtkRenderer()); //B/ ToDo: rendering time calculation - //vtkMapper->GetVtkProp(this)->PokeMatrix(NULL); //B/ ToDo ??: VtkUserTransform + vtkMapper->GetVtkProp(this)->SetAllocatedRenderTime(5000,GetVtkRenderer()); //B/ ToDo: rendering time calculation + //vtkMapper->GetVtkProp(this)->PokeMatrix(NULL); //B/ ToDo ??: VtkUserTransform } if(lastVtkBased == false) { Disable2DOpenGL(); lastVtkBased = true; } } else - if((mapper->IsVtkBased() == false) && (lastVtkBased == true)) - { + if((mapper->IsVtkBased() == false) && (lastVtkBased == true)) + { Enable2DOpenGL(); lastVtkBased = false; } + //Workarround for bug GL_TEXTURE_2D (bug #8188) + GLboolean mode; + GLenum bit = GL_TEXTURE_2D; + GLfloat lineWidth; + glGetFloatv(GL_LINE_WIDTH, &lineWidth); + glGetBooleanv(bit, &mode); + switch(type) { - case mitk::VtkPropRenderer::Opaque: mapper->MitkRenderOpaqueGeometry(this); break; - case mitk::VtkPropRenderer::Translucent: mapper->MitkRenderTranslucentGeometry(this); break; - case mitk::VtkPropRenderer::Overlay: mapper->MitkRenderOverlay(this); break; - case mitk::VtkPropRenderer::Volumetric: mapper->MitkRenderVolumetricGeometry(this); break; + case mitk::VtkPropRenderer::Opaque: mapper->MitkRenderOpaqueGeometry(this); break; + case mitk::VtkPropRenderer::Translucent: mapper->MitkRenderTranslucentGeometry(this); break; + case mitk::VtkPropRenderer::Overlay: mapper->MitkRenderOverlay(this); break; + case mitk::VtkPropRenderer::Volumetric: mapper->MitkRenderVolumetricGeometry(this); break; } + if(mode) + glEnable(bit); + else + glDisable(bit); + + glLineWidth(lineWidth); + //end Workarround for bug GL_TEXTURE_2D (bug #8188) + } if (lastVtkBased == false) Disable2DOpenGL(); - - //fix for bug 1177. In 2D rendering the camera is not needed, but nevertheless it is used by - //the vtk rendering mechanism to determine what is seen (and therefore has to be rendered) - //by using the bounds of the vtkMitkRenderProp - if (sthVtkBased == false) - this->GetVtkRenderer()->ResetCamera(); // Render text if (type == VtkPropRenderer::Overlay) { if (m_TextCollection.size() > 0) { for (TextMapType::iterator it = m_TextCollection.begin(); it != m_TextCollection.end() ; it++) m_TextRenderer->AddViewProp((*it).second); m_TextRenderer->Render(); } } return 1; } /*! \brief PrepareMapperQueue iterates the datatree PrepareMapperQueue iterates the datatree in order to find mappers which shall be rendered. Also, it sortes the mappers wrt to their layer. */ void mitk::VtkPropRenderer::PrepareMapperQueue() { // variable for counting LOD-enabled mappers m_NumberOfVisibleLODEnabledMappers = 0; // Do we have to update the mappers ? - if ( m_LastUpdateTime < GetMTime() || m_LastUpdateTime < GetDisplayGeometry()->GetMTime() ) + if ( m_LastUpdateTime < GetMTime() || m_LastUpdateTime < GetDisplayGeometry()->GetMTime() ) { Update(); - else if (m_MapperID>=2 && m_MapperID < 6) + } + else if (m_MapperID>=1 && m_MapperID < 6) Update(); // remove all text properties before mappers will add new ones m_TextRenderer->RemoveAllViewProps(); for ( unsigned int i=0; iDelete(); } m_TextCollection.clear(); // clear priority_queue m_MappersMap.clear(); int mapperNo = 0; //DataStorage if( m_DataStorage.IsNull() ) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { DataNode::Pointer node = it->Value(); if ( node.IsNull() ) continue; mitk::Mapper::Pointer mapper = node->GetMapper(m_MapperID); + if ( mapper.IsNull() ) continue; // The information about LOD-enabled mappers is required by RenderingManager if ( mapper->IsLODEnabled( this ) && mapper->IsVisible( this ) ) { ++m_NumberOfVisibleLODEnabledMappers; } // mapper without a layer property get layer number 1 int layer = 1; node->GetIntProperty("layer", layer, this); int nr = (layer<<16) + mapperNo; m_MappersMap.insert( std::pair< int, Mapper * >( nr, mapper ) ); mapperNo++; } } /*! \brief Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkPropRenderer::Enable2DOpenGL() { GLint iViewport[4]; - + // Get a copy of the viewport glGetIntegerv( GL_VIEWPORT, iViewport ); - + // Save a copy of the projection matrix so that we can restore it // when it's time to do 3D rendering again. glMatrixMode( GL_PROJECTION ); - glPushMatrix(); + glPushMatrix(); glLoadIdentity(); - + // Set up the orthographic projection glOrtho( - iViewport[0], iViewport[0]+iViewport[2], - iViewport[1], iViewport[1]+iViewport[3], - -1.0, 1.0 - ); + iViewport[0], iViewport[0]+iViewport[2], + iViewport[1], iViewport[1]+iViewport[3], + -1.0, 1.0 + ); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); - glLoadIdentity(); - + glLoadIdentity(); + // Make sure depth testing and lighting are disabled for 2D rendering until // we are finished rendering in 2D - glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ); + glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ); glDisable( GL_DEPTH_TEST ); - glDisable( GL_LIGHTING ); + glDisable( GL_LIGHTING ); } /*! \brief Initialize the VtkPropRenderer Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkPropRenderer::Disable2DOpenGL() { - glPopAttrib(); + glPopAttrib(); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); } void mitk::VtkPropRenderer::Update(mitk::DataNode* datatreenode) { if(datatreenode!=NULL) { mitk::Mapper::Pointer mapper = datatreenode->GetMapper(m_MapperID); if(mapper.IsNotNull()) { Mapper2D* mapper2d=dynamic_cast(mapper.GetPointer()); if(mapper2d != NULL) { if(GetDisplayGeometry()->IsValid()) { VtkMapper2D* vtkmapper2d=dynamic_cast(mapper.GetPointer()); if(vtkmapper2d != NULL) { vtkmapper2d->Update(this); m_VtkMapperPresent=true; } else mapper2d->Update(this); } } else { VtkMapper3D* vtkmapper3d=dynamic_cast(mapper.GetPointer()); if(vtkmapper3d != NULL) { vtkmapper3d->Update(this); vtkmapper3d->UpdateVtkTransform(this); m_VtkMapperPresent=true; } } } } } void mitk::VtkPropRenderer::Update() { if( m_DataStorage.IsNull() ) return; m_VtkMapperPresent = false; mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetAll(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) Update(it->Value()); Modified(); m_LastUpdateTime = GetMTime(); } /*! \brief This method is called from the two Constructors */ void mitk::VtkPropRenderer::InitRenderer(vtkRenderWindow* renderWindow) { BaseRenderer::InitRenderer(renderWindow); if(renderWindow == NULL) { m_InitNeeded = false; m_ResizeNeeded = false; return; } m_InitNeeded = true; m_ResizeNeeded = true; m_LastUpdateTime = 0; } /*! \brief Resize the OpenGL Window */ void mitk::VtkPropRenderer::Resize(int w, int h) { BaseRenderer::Resize(w, h); - m_RenderingManager->RequestUpdate(this->GetRenderWindow()); } void mitk::VtkPropRenderer::InitSize(int w, int h) { m_RenderWindow->SetSize(w,h); Superclass::InitSize(w, h); Modified(); Update(); if(m_VtkRenderer!=NULL) { int w=vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); m_VtkRenderer->ResetCamera(); vtkObject::SetGlobalWarningDisplay(w); } } void mitk::VtkPropRenderer::SetMapperID(const MapperSlotId mapperId) { if(m_MapperID != mapperId) Superclass::SetMapperID(mapperId); // Workaround for GL Displaylist Bug checkState(); } /*! \brief Activates the current renderwindow. */ void mitk::VtkPropRenderer::MakeCurrent() { if(m_RenderWindow!=NULL) - m_RenderWindow->MakeCurrent(); + m_RenderWindow->MakeCurrent(); } void mitk::VtkPropRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const { if(m_VtkMapperPresent) { //m_WorldPointPicker->SetTolerance (0.0001); switch ( m_PickingMode ) { - case (WorldPointPicking) : - { - m_WorldPointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); - vtk2itk(m_WorldPointPicker->GetPickPosition(), worldPoint); - break; - } - case (PointPicking) : - { - // create a new vtkRenderer - // give it all necessary information (camera position, etc.) - // get all surfaces from datastorage, get actors from them - // add all those actors to the new renderer - // give this new renderer to pointpicker - /* + case (WorldPointPicking) : + { + m_WorldPointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); + vtk2itk(m_WorldPointPicker->GetPickPosition(), worldPoint); + break; + } + case (PointPicking) : + { + // create a new vtkRenderer + // give it all necessary information (camera position, etc.) + // get all surfaces from datastorage, get actors from them + // add all those actors to the new renderer + // give this new renderer to pointpicker + /* vtkRenderer* pickingRenderer = vtkRenderer::New(); pickingRenderer->SetActiveCamera( ); - + DataStorage* dataStorage = m_DataStorage; TNodePredicateDataType isSurface; DataStorage::SetOfObjects::ConstPointer allSurfaces = dataStorage->GetSubset( isSurface ); MITK_INFO << "in picking: got " << allSurfaces->size() << " surfaces." << std::endl; for (DataStorage::SetOfObjects::const_iterator iter = allSurfaces->begin(); iter != allSurfaces->end(); ++iter) { const DataNode* currentNode = *iter; VtkMapper3D* baseVtkMapper3D = dynamic_cast( currentNode->GetMapper( BaseRenderer::Standard3D ) ); if ( baseVtkMapper3D ) { vtkActor* actor = dynamic_cast( baseVtkMapper3D->GetViewProp() ); if (actor) { MITK_INFO << "a" << std::flush; pickingRenderer->AddActor( actor ); } } } MITK_INFO << ";" << std::endl; */ - m_PointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); - vtk2itk(m_PointPicker->GetPickPosition(), worldPoint); - break; - } + m_PointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); + vtk2itk(m_PointPicker->GetPickPosition(), worldPoint); + break; + } } } else { Superclass::PickWorldPoint(displayPoint, worldPoint); } } mitk::DataNode * -mitk::VtkPropRenderer::PickObject( const Point2D &displayPosition, Point3D &worldPosition ) const + mitk::VtkPropRenderer::PickObject( const Point2D &displayPosition, Point3D &worldPosition ) const { if ( m_VtkMapperPresent ) { m_CellPicker->InitializePickList(); // Iterate over all DataStorage objects to determine all vtkProps intended // for picking DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for ( DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); - it != allObjects->End(); - ++it ) + it != allObjects->End(); + ++it ) { DataNode *node = it->Value(); if ( node == NULL ) continue; bool pickable = false; node->GetBoolProperty( "pickable", pickable ); if ( !pickable ) continue; VtkMapper3D *mapper = dynamic_cast< VtkMapper3D * > - ( node->GetMapper( m_MapperID ) ); + ( node->GetMapper( m_MapperID ) ); if ( mapper == NULL ) continue; vtkProp *prop = mapper->GetVtkProp( (mitk::BaseRenderer *)this ); if ( prop == NULL ) continue; m_CellPicker->AddPickList( prop ); } // Do the picking and retrieve the picked vtkProp (if any) m_CellPicker->PickFromListOn(); m_CellPicker->Pick( displayPosition[0], displayPosition[1], 0.0, m_VtkRenderer ); m_CellPicker->PickFromListOff(); vtk2itk( m_CellPicker->GetPickPosition(), worldPosition ); vtkProp *prop = m_CellPicker->GetViewProp(); - + if ( prop == NULL ) { return NULL; } // Iterate over all DataStorage objects to determine if the retrieved // vtkProp is owned by any associated mapper. for ( DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); - it != allObjects->End(); - ++it) + it != allObjects->End(); + ++it) { DataNode::Pointer node = it->Value(); if ( node.IsNull() ) continue; mitk::Mapper::Pointer mapper = node->GetMapper( m_MapperID ); if ( mapper.IsNull() ) continue; if ( mapper->HasVtkProp( prop, const_cast< mitk::VtkPropRenderer * >( this ) ) ) { return node; } } return NULL; } else { return Superclass::PickObject( displayPosition, worldPosition ); } }; /*! \brief Writes some 2D text as overlay. Function returns an unique int Text_ID for each call, which can be used via the GetTextLabelProperty(int text_id) function in order to get a vtkTextProperty. This property enables the setup of font, font size, etc. */ int mitk::VtkPropRenderer::WriteSimpleText(std::string text, double posX, double posY, double color1, double color2, double color3) { - if(text.size() > 0) + if(text.size() > 0) { vtkTextActor* textActor = vtkTextActor::New(); textActor->SetPosition(posX,posY); textActor->SetInput(text.c_str()); textActor->GetTextProperty()->SetColor(color1, color2, color3); //TODO: Read color from node property int text_id = m_TextCollection.size(); m_TextCollection.insert(TextMapType::value_type(text_id,textActor)); return text_id; } return -1; } /*! \brief Can be used in order to get a vtkTextProperty for a specific text_id. This property enables the setup of font, font size, etc. */ vtkTextProperty* mitk::VtkPropRenderer::GetTextLabelProperty(int text_id) { return this->m_TextCollection[text_id]->GetTextProperty(); } void mitk::VtkPropRenderer::InitPathTraversal() { if (m_DataStorage.IsNotNull()) { m_PickingObjects = m_DataStorage->GetAll(); m_PickingObjectsIterator = m_PickingObjects->begin(); } } vtkAssemblyPath* mitk::VtkPropRenderer::GetNextPath() { if (m_DataStorage.IsNull() ) { return NULL; } if ( m_PickingObjectsIterator == m_PickingObjects->end() ) { return NULL; } vtkAssemblyPath* returnPath = vtkAssemblyPath::New(); //returnPath->Register(NULL); bool success = false; - + while (!success) { // loop until AddNode can be called successfully const DataNode* node = *m_PickingObjectsIterator; if (node) { Mapper* mapper = node->GetMapper( BaseRenderer::Standard3D ); if (mapper) { VtkMapper3D* vtkmapper = dynamic_cast( mapper ); if (vtkmapper) { vtkProp* prop = vtkmapper->GetVtkProp(this); if ( prop && prop->GetVisibility() ) { // add to assembly path returnPath->AddNode( prop, prop->GetMatrix() ); success = true; } } } } ++m_PickingObjectsIterator; if ( m_PickingObjectsIterator == m_PickingObjects->end() ) break; } if ( success ) { return returnPath; } else { return NULL; } } void mitk::VtkPropRenderer::ReleaseGraphicsResources(vtkWindow *renWin) { if( m_DataStorage.IsNull() ) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::const_iterator iter = allObjects->begin(); iter != allObjects->end(); ++iter) { DataNode::Pointer node = *iter; if ( node.IsNull() ) continue; Mapper::Pointer mapper = node->GetMapper(m_MapperID); if(mapper.IsNotNull()) mapper->ReleaseGraphicsResources(renWin); } } const vtkWorldPointPicker *mitk::VtkPropRenderer::GetWorldPointPicker() const { return m_WorldPointPicker; } const vtkPointPicker *mitk::VtkPropRenderer::GetPointPicker() const { return m_PointPicker; } const vtkCellPicker *mitk::VtkPropRenderer::GetCellPicker() const { return m_CellPicker; } mitk::VtkPropRenderer::MappersMapType mitk::VtkPropRenderer::GetMappersMap() const { return m_MappersMap; } // Workaround for GL Displaylist bug static int glWorkAroundGlobalCount = 0; bool mitk::VtkPropRenderer::useImmediateModeRendering() { return glWorkAroundGlobalCount>1; } void mitk::VtkPropRenderer::checkState() { if (m_MapperID == Standard3D) { if (!didCount) { didCount = true; glWorkAroundGlobalCount++; if (glWorkAroundGlobalCount == 2) { MITK_INFO << "Multiple 3D Renderwindows active...: turning Immediate Rendering ON for legacy mappers"; -// vtkMapper::GlobalImmediateModeRenderingOn(); + // vtkMapper::GlobalImmediateModeRenderingOn(); } //MITK_INFO << "GLOBAL 3D INCREASE " << glWorkAroundGlobalCount << "\n"; } } else { if(didCount) { didCount=false; glWorkAroundGlobalCount--; if(glWorkAroundGlobalCount==1) { MITK_INFO << "Single 3D Renderwindow active...: turning Immediate Rendering OFF for legacy mappers"; -// vtkMapper::GlobalImmediateModeRenderingOff(); + // vtkMapper::GlobalImmediateModeRenderingOff(); } //MITK_INFO << "GLOBAL 3D DECREASE " << glWorkAroundGlobalCount << "\n"; } - } + } +} + +//### Contains all methods which are neceassry before each VTK Render() call +void mitk::VtkPropRenderer::PrepareRender() +{ + // if(!m_2DCameraInitialized) + // { + m_2DCameraInitialized = Initialize2DvtkCamera(); //Set parallel projection etc. TODO: call only once per RW + // } + AdjustCameraToScene(); //Prepare camera for 2D render windows +} + +bool mitk::VtkPropRenderer::Initialize2DvtkCamera(){ + if(this->GetMapperID() == Standard2D) + { + //activate parallel projection for 2D + this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(true); + //turn the light out in the scene in order to render correct grey values. + //TODO Implement a property for light in the 2D render windows (in another method) + this->GetVtkRenderer()->RemoveAllLights(); + //remove the VTK interaction + this->GetVtkRenderer()->GetRenderWindow()->SetInteractor(NULL); + } + return true; +} + +void mitk::VtkPropRenderer::AdjustCameraToScene(){ + if(this->GetMapperID() == Standard2D) + { + const mitk::DisplayGeometry* displayGeometry = this->GetDisplayGeometry(); + + double objectHeightInMM = this->GetCurrentWorldGeometry2D()->GetExtentInMM(1);//the height of the current object slice in mm + double displayHeightInMM = displayGeometry->GetSizeInMM()[1]; //the display height in mm (gets smaller when you zoom in) + double zoomFactor = objectHeightInMM/displayHeightInMM; //displayGeometry->GetScaleFactorMMPerDisplayUnit() + //determine how much of the object can be displayed + + Vector2D displayGeometryOriginInMM = displayGeometry->GetOriginInMM(); //top left of the render window (Origin) + Vector2D displayGeometryCenterInMM = displayGeometryOriginInMM + displayGeometry->GetSizeInMM()*0.5; //center of the render window: (Origin + Size/2) + + //Scale the rendered object: + //The image is scaled by a single factor, because in an orthographic projection sizes + //are preserved (so you cannot scale X and Y axis with different parameters). The + //parameter sets the size of the total display-volume. If you set this to the image + //height, the image plus a border with the size of the image will be rendered. + //Therefore, the size is imageHeightInMM / 2. + this->GetVtkRenderer()->GetActiveCamera()->SetParallelScale(objectHeightInMM*0.5 ); + //zooming with the factor calculated by dividing displayHeight through imegeHeight. The factor is inverse, because the VTK zoom method is working inversely. + this->GetVtkRenderer()->GetActiveCamera()->Zoom(zoomFactor); + + //the center of the view-plane + double viewPlaneCenter[3]; + viewPlaneCenter[0] = displayGeometryCenterInMM[0]; + viewPlaneCenter[1] = displayGeometryCenterInMM[1]; + viewPlaneCenter[2] = 0.0; //the view-plane is located in the XY-plane with Z=0.0 + + //define which direction is "up" for the ciamera (like default for vtk (0.0, 1.0, 0.0) + double cameraUp[3]; + cameraUp[0] = 0.0; + cameraUp[1] = 1.0; + cameraUp[2] = 0.0; + + //the position of the camera (center[0], center[1], 900000) + double cameraPosition[3]; + cameraPosition[0] = viewPlaneCenter[0]; + cameraPosition[1] = viewPlaneCenter[1]; + cameraPosition[2] = 900000.0; //Reason for 900000: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. + + //set the camera corresponding to the textured plane + vtkSmartPointer camera = this->GetVtkRenderer()->GetActiveCamera(); + if (camera) + { + camera->SetPosition( cameraPosition ); //set the camera position on the textured plane normal (in our case this is the view plane normal) + camera->SetFocalPoint( viewPlaneCenter ); //set the focal point to the center of the textured plane + camera->SetViewUp( cameraUp ); //set the view-up for the camera + // double distance = sqrt((cameraPosition[2]-viewPlaneCenter[2])*(cameraPosition[2]-viewPlaneCenter[2])); + // camera->SetClippingRange(distance-50, distance+50); //Reason for huge range: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. + camera->SetClippingRange(0.1, 1000000); //Reason for huge range: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. + } + + const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( this->GetCurrentWorldGeometry2D() ); + if ( planeGeometry != NULL ) + { + //Transform the camera to the current position (transveral, coronal and saggital plane). + //This is necessary, because the SetUserTransform() method does not manipulate the vtkCamera. + //(Without not all three planes would be visible). + vtkSmartPointer trans = vtkSmartPointer::New(); + vtkSmartPointer matrix = vtkSmartPointer::New(); + Point3D origin; + Vector3D right, bottom, normal; + + origin = planeGeometry->GetOrigin(); + right = planeGeometry->GetAxisVector( 0 ); // right = Extent of Image in mm (worldspace) + bottom = planeGeometry->GetAxisVector( 1 ); + normal = planeGeometry->GetNormal(); + + right.Normalize(); + bottom.Normalize(); + normal.Normalize(); + + matrix->SetElement(0, 0, right[0]); + matrix->SetElement(1, 0, right[1]); + matrix->SetElement(2, 0, right[2]); + matrix->SetElement(0, 1, bottom[0]); + matrix->SetElement(1, 1, bottom[1]); + matrix->SetElement(2, 1, bottom[2]); + matrix->SetElement(0, 2, normal[0]); + matrix->SetElement(1, 2, normal[1]); + matrix->SetElement(2, 2, normal[2]); + matrix->SetElement(0, 3, origin[0]); + matrix->SetElement(1, 3, origin[1]); + matrix->SetElement(2, 3, origin[2]); + matrix->SetElement(3, 0, 0.0); + matrix->SetElement(3, 1, 0.0); + matrix->SetElement(3, 2, 0.0); + matrix->SetElement(3, 3, 1.0); + + trans->SetMatrix(matrix); + //Transform the camera to the current position (transveral, coronal and saggital plane). + this->GetVtkRenderer()->GetActiveCamera()->ApplyTransform(trans); + } + } } diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.h b/Core/Code/Rendering/mitkVtkPropRenderer.h index ed0f05e192..588018d05a 100644 --- a/Core/Code/Rendering/mitkVtkPropRenderer.h +++ b/Core/Code/Rendering/mitkVtkPropRenderer.h @@ -1,187 +1,241 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2007-09-22 12:01:41 +0200 (Sa, 22 Sep 2007) $ Version: $Revision: 12241 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D #define MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D #include #include "mitkBaseRenderer.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include #include #include class vtkRenderWindow; class vtkLight; class vtkLightKit; class vtkWorldPointPicker; class vtkPointPicker; class vtkCellPicker; class vtkTextActor; class vtkTextProperty; class vtkAssemblyPath; namespace mitk { class Mapper; /*! \brief VtkPropRenderer VtkPropRenderer organizes the MITK rendering process. The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. VtkPropRenderer replaces the old OpenGLRenderer. \sa rendering \ingroup rendering */ class MITK_CORE_EXPORT VtkPropRenderer : public BaseRenderer { // Workaround for Displaylistbug private: bool didCount; void checkState(); // Workaround END public: mitkClassMacro(VtkPropRenderer,BaseRenderer); mitkNewMacro3Param(VtkPropRenderer, const char*, vtkRenderWindow *, mitk::RenderingManager* ); typedef std::map MappersMapType; // Render - called by vtkMitkRenderProp, returns the number of props rendered enum RenderType{Opaque,Translucent,Overlay,Volumetric}; int Render(RenderType type); + /** \brief This methods contains all method neceassary before a VTK Render() call */ + virtual void PrepareRender(); + // Active current renderwindow virtual void MakeCurrent(); virtual void SetDataStorage( mitk::DataStorage* storage ); ///< set the datastorage that will be used for rendering virtual void InitRenderer(vtkRenderWindow* renderwindow); virtual void Update(mitk::DataNode* datatreenode); virtual void SetMapperID(const MapperSlotId mapperId); // Size virtual void InitSize(int w, int h); virtual void Resize(int w, int h); // Picking enum PickingMode{ WorldPointPicking, PointPicking }; itkSetEnumMacro( PickingMode, PickingMode ); itkGetEnumMacro( PickingMode, PickingMode ); virtual void PickWorldPoint(const Point2D& displayPoint, Point3D& worldPoint) const; virtual mitk::DataNode *PickObject( const Point2D &displayPosition, Point3D &worldPosition ) const; // Simple text rendering method int WriteSimpleText(std::string text, double posX, double posY, double color1 = 0.0, double color2 = 1.0, double color3 = 0.0); vtkTextProperty * GetTextLabelProperty(int text_id); // Initialization / geometry handling /** This method calculates the bounds of the DataStorage (if it contains any * valid data), creates a geometry from these bounds and sets it as world * geometry of the renderer. * * Call this method to re-initialize the renderer to the current DataStorage * (e.g. after loading an additional dataset), to ensure that the view is * aligned correctly. */ virtual bool SetWorldGeometryToDataStorageBounds(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ void InitPathTraversal(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ vtkAssemblyPath* GetNextPath(); const vtkWorldPointPicker *GetWorldPointPicker() const; const vtkPointPicker *GetPointPicker() const; const vtkCellPicker *GetCellPicker() const; /** * \brief Release vtk-based graphics resources. Called by * vtkMitkRenderProp::ReleaseGraphicsResources. */ virtual void ReleaseGraphicsResources(vtkWindow *renWin); MappersMapType GetMappersMap() const; static bool useImmediateModeRendering(); protected: VtkPropRenderer( const char* name = "VtkPropRenderer", vtkRenderWindow * renWin = NULL, mitk::RenderingManager* rm = NULL ); virtual ~VtkPropRenderer(); virtual void Update(); private: + /** \brief This method sets up the camera on the actor (e.g. an image) of all + * 2D vtkRenderWindows. The view is centered; zooming and panning of VTK are called inside. + * + * \image html ImageMapperdisplayGeometry.png + * + * Similar to the textured plane of an image + * (cf. void mitkImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, + * vtkFloatingPointType planeBounds[6])), the mitkDisplayGeometry defines a view plane (or + * projection plane). This plane is used to set the camera parameters. The view plane + * center (VC) is important for camera positioning (cf. the image above). + * + * The following figure shows the combination of the textured plane and the view plane. + * + * \image html cameraPositioning.png + * + * The view plane center (VC) is the center of the textured plane (C) and the focal point + * (FP) at the same time. The FP defines the direction the camera faces. Since + * the textured plane is always in the XY-plane and orthographic projection is applied, the + * distance between camera and plane is theoretically irrelevant (because in the orthographic + * projection the center of projection is at infinity and the size of objects depends only on + * a scaling parameter). As a consequence, the direction of projection (DOP) is (0; 0; -1). + * The camera up vector is always defined as (0; 1; 0). + * + * \warning Due to a VTK clipping bug the distance between textured plane and camera is really huge. + * Otherwise, VTK would clip off some slices. Same applies for the clipping range size. + * + * \note The camera position is defined through the mitkDisplayGeometry. + * This facilitates zooming and panning, because the display + * geometry changes and the textured plane does not. + * + * \image html scaling.png + * + * The textured plane is scaled to fill the render window via + * camera->SetParallelScale( imageHeightInMM / 2). In the orthographic projection all extends, + * angles and sizes are preserved. Therefore, the image is scaled by one parameter which defines + * the size of the rendered image. A higher value will result in smaller images. In order to render + * just the whole image, the scale is set to half of the image height in worldcoordinates + * (cf. the picture above). + * + * For zooming purposes, a factor is computed as follows: + * factor = image height / display height (in worldcoordinates). + * When the display geometry gets smaller (zoom in), the factor becomes bigger. When the display + * geometry gets bigger (zoom out), the factor becomes smaller. The used VTK method + * camera->Zoom( factor ) also works with an inverse scale. + */ + void AdjustCameraToScene(); + // switch between orthogonal opengl projection (2D rendering via mitk::GLMapper2D) and perspective projection (3D rendering) void Enable2DOpenGL(); void Disable2DOpenGL(); // prepare all mitk::mappers for rendering void PrepareMapperQueue(); + /** \brief Set parallel projection, remove the interactor and the lights of VTK. */ + bool Initialize2DvtkCamera(); + bool m_InitNeeded; bool m_ResizeNeeded; bool m_VtkMapperPresent; bool m_NewRenderer; + bool m_2DCameraInitialized; // Picking vtkWorldPointPicker * m_WorldPointPicker; vtkPointPicker * m_PointPicker; vtkCellPicker * m_CellPicker; PickingMode m_PickingMode; // Explicit use of SmartPointer to avoid circular #includes itk::SmartPointer< mitk::Mapper > m_CurrentWorldGeometry2DMapper; vtkLightKit* m_LightKit; // sorted list of mappers MappersMapType m_MappersMap; // rendering of text vtkRenderer * m_TextRenderer; typedef std::map TextMapType; TextMapType m_TextCollection; DataStorage::SetOfObjects::ConstPointer m_PickingObjects; DataStorage::SetOfObjects::const_iterator m_PickingObjectsIterator; }; } // namespace mitk #endif /* MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D */ diff --git a/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.cpp b/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.cpp new file mode 100644 index 0000000000..bb6dfd66c9 --- /dev/null +++ b/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.cpp @@ -0,0 +1,266 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. + +=========================================================================*/ + +#include "vtkMitkApplyLevelWindowToRGBFilter.h" +#include +#include +#include + +//used for acos etc. +#include + +//used for PI +#include + +static const double PI = itk::Math::pi; + +vtkMitkApplyLevelWindowToRGBFilter::vtkMitkApplyLevelWindowToRGBFilter():m_MinOqacity(0.0),m_MaxOpacity(255.0) +{ +} + +vtkMitkApplyLevelWindowToRGBFilter::~vtkMitkApplyLevelWindowToRGBFilter() +{ +} + +void vtkMitkApplyLevelWindowToRGBFilter::SetLookupTable(vtkScalarsToColors *lookupTable) +{ + m_LookupTable = lookupTable; +} + +vtkScalarsToColors* vtkMitkApplyLevelWindowToRGBFilter::GetLookupTable() +{ + return m_LookupTable; +} + +//This code was copied from the iil. The template works only for float and double. +//Internal method which should never be used anywhere else and should not be in th header. +// Convert color pixels from (R,G,B) to (H,S,I). +// Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. +template +void RGBtoHSI(T* RGB, T* HSI) +{ + T R = RGB[0], + G = RGB[1], + B = RGB[2], + nR = (R<0?0:(R>255?255:R))/255, + nG = (G<0?0:(G>255?255:G))/255, + nB = (B<0?0:(B>255?255:B))/255, + m = nR0) H = (nB<=nG)?theta:360-theta; + if (sum>0) S = 1 - 3/sum*m; + I = sum/3; + HSI[0] = (T)H; + HSI[1] = (T)S; + HSI[2] = (T)I; +} + +//This code was copied from the iil. The template works only for float and double. +//Internal method which should never be used anywhere else and should not be in th header. +// Convert color pixels from (H,S,I) to (R,G,B). +template +void HSItoRGB(T* HSI, T* RGB) +{ + T H = (T)HSI[0], + S = (T)HSI[1], + I = (T)HSI[2], + a = I*(1-S), + R = 0, G = 0, B = 0; + if (H<120) { + B = a; + R = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); + G = 3*I-(R+B); + } else if (H<240) { + H-=120; + R = a; + G = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); + B = 3*I-(R+G); + } else { + H-=240; + G = a; + B = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); + R = 3*I-(G+B); + } + R*=255; G*=255; B*=255; + RGB[0] = (T)(R<0?0:(R>255?255:R)); + RGB[1] = (T)(G<0?0:(G>255?255:G)); + RGB[2] = (T)(B<0?0:(B>255?255:B)); +} + +//Internal method which should never be used anywhere else and should not be in th header. +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template + void vtkCalculateIntensityFromLookupTable(vtkMitkApplyLevelWindowToRGBFilter *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], T *) +{ + vtkImageIterator inputIt(inData, outExt); + vtkImageIterator outputIt(outData, outExt); + vtkLookupTable* lookupTable; + int maxC; + int indexComponents = 3; //RGB case + double imgRange[2]; + double tableRange[2]; + + lookupTable = dynamic_cast(self->GetLookupTable()); + + lookupTable->GetTableRange(tableRange); + inData->GetScalarRange(imgRange); + + //parameters for RGB level window + double scale = (tableRange[1] -tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0); + double bias = tableRange[0] * scale; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents(); + + //parameters for opaque level window + double scaleOpac = (self->GetMaxOpacity() -self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0); + double biasOpac = self->GetMinOpacity() * scaleOpac; + + // Loop through ouput pixels + while (!outputIt.IsAtEnd()) + { + T* inputSI = inputIt.BeginSpan(); + T* outputSI = outputIt.BeginSpan(); + T* outputSIEnd = outputIt.EndSpan(); + while (outputSI != outputSIEnd) + { + double rgb[3], alpha, hsi[3]; + + // level/window mechanism for intensity in HSI space + rgb[0] = static_cast(*inputSI); inputSI++; + rgb[1] = static_cast(*inputSI); inputSI++; + rgb[2] = static_cast(*inputSI); inputSI++; + + RGBtoHSI(rgb,hsi); + hsi[2] = hsi[2] * 255.0 * scale - bias; + hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2])); + hsi[2] /= 255.0; + HSItoRGB(hsi,rgb); + + *outputSI = static_cast(rgb[0]); outputSI++; + *outputSI = static_cast(rgb[1]); outputSI++; + *outputSI = static_cast(rgb[2]); outputSI++; + + //RGBA case + if(maxC >= 4) + { + indexComponents = 4; //now its the RGBA case + // level/window mechanism for opacity + alpha = static_cast(*inputSI); inputSI++; + alpha = alpha * scaleOpac - biasOpac; + if(alpha > 255.0) + { + alpha = 255.0; + } + else if(alpha < 0.0) + { + alpha = 0.0; + } + *outputSI = static_cast(alpha); outputSI++; + } + + for (int i = indexComponents; i < maxC; i++) + { + *outputSI++ = *inputSI++; + } + } + inputIt.NextSpan(); + outputIt.NextSpan(); + } +} + +void vtkMitkApplyLevelWindowToRGBFilter::ExecuteInformation() +{ + vtkImageData *input = this->GetInput(); + vtkImageData *output = this->GetOutput(); + + if (!input) + { + vtkErrorMacro(<< "Input not set."); + return; + } + output->CopyTypeSpecificInformation( input ); + + int extent[6]; + input->GetWholeExtent(extent); + output->SetExtent(extent); + output->SetWholeExtent(extent); + output->SetUpdateExtent(extent); + output->AllocateScalars(); + + switch (input->GetScalarType()) + { + vtkTemplateMacro( + vtkCalculateIntensityFromLookupTable( this, + input, + output, extent, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//Method to run the filter in different threads. +void vtkMitkApplyLevelWindowToRGBFilter::ThreadedExecute(vtkImageData *inData, + vtkImageData *outData, + int extent[6], int /*id*/) +{ + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkCalculateIntensityFromLookupTable( this, + inData, + outData, + extent, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkMitkApplyLevelWindowToRGBFilter::ExecuteInformation( + vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) +{ +} + +void vtkMitkApplyLevelWindowToRGBFilter::SetMinOpacity(double minOpacity) +{ + m_MinOqacity = minOpacity; +} + +inline double vtkMitkApplyLevelWindowToRGBFilter::GetMinOpacity() const +{ + return m_MinOqacity; +} + +void vtkMitkApplyLevelWindowToRGBFilter::SetMaxOpacity(double maxOpacity) +{ + m_MaxOpacity = maxOpacity; +} + +inline double vtkMitkApplyLevelWindowToRGBFilter::GetMaxOpacity() const +{ + return m_MaxOpacity; +} diff --git a/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.h b/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.h new file mode 100644 index 0000000000..73db7a85c3 --- /dev/null +++ b/Core/Code/Rendering/vtkMitkApplyLevelWindowToRGBFilter.h @@ -0,0 +1,81 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-07-14 19:11:20 +0200 (Tue, 14 Jul 2009) $ +Version: $Revision: 18127 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. + +=========================================================================*/ + +#ifndef __vtkMitkApplyLevelWindowToRGBFilter_h +#define __vtkMitkApplyLevelWindowToRGBFilter_h + +class vtkScalarsToColors; +#include +#include + +#include +/** Documentation +* \brief Applies the color and opacity level window to RGB(A) images. +* +* This filter is used to apply the color level window to RBG images (e.g. +* diffusion tensor images). Therefore, the RGB channels are converted to +* the HSI color space, where the level window can be applied. Afterwards, +* the HSI values transformed back to the RGB space. +* +* The filter is also able to apply an opacity level window to RGBA images. +* +* \ingroup Renderer +*/ +class MITK_CORE_EXPORT vtkMitkApplyLevelWindowToRGBFilter : public vtkImageToImageFilter +{ +public: + /** \brief Get the lookup table for the RGB level window */ + vtkScalarsToColors* GetLookupTable(); + /** \brief Set the lookup table for the RGB level window */ + void SetLookupTable(vtkScalarsToColors *lookupTable); + + /** \brief Get/Set the lower window opacity for the alpha level window */ + void SetMinOpacity(double minOpacity); + inline double GetMinOpacity() const; + + /** \brief Get/Set the upper window opacity for the alpha level window */ + void SetMaxOpacity(double maxOpacity); + inline double GetMaxOpacity() const; + + /** Default constructor. */ + vtkMitkApplyLevelWindowToRGBFilter(); + /** Default deconstructor. */ + ~vtkMitkApplyLevelWindowToRGBFilter(); +protected: + /** \brief Method for threaded execution of the filter. + * \param *inData: The input. + * \param *outData: The output of the filter. + * \param extent[6]: Specefies the region of the image to be updated inside this thread. + * It is a six-component array of the form (xmin, xmax, ymin, ymax, zmin, zmax). + * \param id: The thread id. + */ + void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,int extent[6], int id); + + /** Standard VTK filter method to apply the filter. See VTK documentation.*/ + void ExecuteInformation(); + /** Standard VTK filter method to apply the filter. See VTK documentation. Not used at the moment.*/ + void ExecuteInformation(vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)); + +private: + /** m_LookupTable contains the lookup table for the RGB level window.*/ + vtkScalarsToColors* m_LookupTable; + /** m_MinOqacity contains the lower bound for the alpha level window.*/ + double m_MinOqacity; + /** m_MinOqacity contains the upper bound for the alpha level window.*/ + double m_MaxOpacity; +}; +#endif diff --git a/Core/Code/Rendering/vtkMitkRenderProp.cpp b/Core/Code/Rendering/vtkMitkRenderProp.cpp index 88e3ab6c3e..33f4226f97 100644 --- a/Core/Code/Rendering/vtkMitkRenderProp.cpp +++ b/Core/Code/Rendering/vtkMitkRenderProp.cpp @@ -1,106 +1,125 @@ /*========================================================================= - Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2007-08-17 16:41:18 +0200 (Fr, 17 Aug 2007) $ Version: $Revision: 11618 $ - + Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "vtkMitkRenderProp.h" #include #include #include #include "mitkVtkMapper3D.h" +#include "mitkVtkMapper2D.h" + vtkStandardNewMacro(vtkMitkRenderProp); vtkMitkRenderProp::vtkMitkRenderProp() { } vtkMitkRenderProp::~vtkMitkRenderProp() { } double *vtkMitkRenderProp::GetBounds() { return const_cast(m_VtkPropRenderer->GetBounds()); } void vtkMitkRenderProp::SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer) { this->m_VtkPropRenderer = propRenderer; } int vtkMitkRenderProp::RenderOpaqueGeometry(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Opaque); } int vtkMitkRenderProp::RenderOverlay(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Overlay); } void vtkMitkRenderProp::ReleaseGraphicsResources(vtkWindow* window) { m_VtkPropRenderer->ReleaseGraphicsResources(window); } void vtkMitkRenderProp::InitPathTraversal() { m_VtkPropRenderer->InitPathTraversal(); } vtkAssemblyPath* vtkMitkRenderProp::GetNextPath() { return m_VtkPropRenderer->GetNextPath(); } //BUG (#1551) added method depth peeling int vtkMitkRenderProp::HasTranslucentPolygonalGeometry() { typedef std::map MappersMapType; MappersMapType mappersMap = m_VtkPropRenderer->GetMappersMap(); for(MappersMapType::iterator it = mappersMap.begin(); it != mappersMap.end(); it++) { mitk::Mapper * mapper = (*it).second; - mitk::VtkMapper3D::Pointer vtkMapper = dynamic_cast(mapper); - if(vtkMapper) + mitk::VtkMapper3D::Pointer vtkMapper3D = dynamic_cast(mapper); + if(vtkMapper3D) { // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly // manually (see issue #8186 committed to VTK's Mantis issue tracker) // --> VTK bug resolved on 2008-12-01 vtkPropAssembly *propAssembly = dynamic_cast< vtkPropAssembly * >( - vtkMapper->GetVtkProp(m_VtkPropRenderer) ); + vtkMapper3D->GetVtkProp(m_VtkPropRenderer) ); if ( propAssembly ) { propAssembly->InitPathTraversal(); } - - if (vtkMapper->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) + + if (vtkMapper3D->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) return 1; } - + + //TODO bad solution. + mitk::VtkMapper2D::Pointer vtkMapper2D = dynamic_cast(mapper); + if(vtkMapper2D) + { + // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly + // manually (see issue #8186 committed to VTK's Mantis issue tracker) + // --> VTK bug resolved on 2008-12-01 + vtkPropAssembly *propAssembly = dynamic_cast< vtkPropAssembly * >( + vtkMapper2D->GetVtkProp(m_VtkPropRenderer) ); + if ( propAssembly ) + { + propAssembly->InitPathTraversal(); //TODO why is this called here??? + } + + if (vtkMapper2D->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) { + return 1; + } + } } return 0; } int vtkMitkRenderProp::RenderTranslucentPolygonalGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Translucent); } int vtkMitkRenderProp::RenderVolumetricGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Volumetric); } diff --git a/Core/Code/Testing/mitkDataNodeTest.cpp b/Core/Code/Testing/mitkDataNodeTest.cpp index b46ee9b5d0..d4b9d52736 100644 --- a/Core/Code/Testing/mitkDataNodeTest.cpp +++ b/Core/Code/Testing/mitkDataNodeTest.cpp @@ -1,301 +1,301 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $ Version: $Revision: 7837 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkDataNode.h" #include #include "mitkVtkPropRenderer.h" #include "mitkTestingMacros.h" #include "mitkGlobalInteraction.h" #include //Basedata Test #include #include #include #include #include #include #include #include //Mapper Test #include #include -#include +#include #include #include #include #include #include #include #include //Interactors #include #include //Propertylist Test /** * Simple example for a test for the (non-existent) class "DataNode". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ class mitkDataNodeTestClass { public: static void TestDataSetting(mitk::DataNode::Pointer dataNode) { mitk::BaseData::Pointer baseData; //NULL pointer Test dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a NULL pointer was set correctly" ) baseData = mitk::RenderWindowFrame::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a RenderWindowFrame object was set correctly" ) // MITK_TEST_CONDITION( baseData->GetGeometry(0)->GetVtkTransform() == dataNode->GetVtkTransform(0), "Testing if a NULL pointer was set correctly" ) baseData = mitk::GeometryData::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a GeometryData object was set correctly" ) baseData = mitk::Geometry2DData::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Geometry2DData object was set correctly" ) baseData = mitk::GradientBackground::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a GradientBackground object was set correctly" ) baseData = mitk::ManufacturerLogo::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a ManufacturerLogo object was set correctly" ) baseData = mitk::PointSet::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a PointSet object was set correctly" ) baseData = mitk::Image::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Image object was set correctly" ) baseData = mitk::Surface::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Surface object was set correctly" ) } static void TestMapperSetting(mitk::DataNode::Pointer dataNode) { //tests the SetMapper() method //in dataNode is a mapper vector which can be accessed by index //in this test method we use only slot 0 (filled with null) and slot 1 //so we also test the destructor of the mapper classes mitk::Mapper::Pointer mapper; dataNode->SetMapper(0,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(0), "Testing if a NULL pointer was set correctly" ) mapper = mitk::Geometry2DDataMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a Geometry2DDataMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) - mapper = mitk::ImageMapperGL2D::New(); + mapper = mitk::ImageVtkMapper2D::New(); dataNode->SetMapper(1,mapper); - MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ImageMapperGL2D was set correctly" ) + MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ImageVtkMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::PointSetGLMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PointSetGLMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PolyDataGLMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::SurfaceGLMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a SurfaceGLMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::Geometry2DDataVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a Geometry2DDataVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::PointSetVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a PointSetVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::SurfaceVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a SurfaceVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::VolumeDataVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a VolumeDataVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) //linker error //mapper = mitk::LineVtkMapper3D::New(); //dataNode->SetMapper(1,mapper); //MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a LineVtkMapper3D was set correctly" ) //MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) } static void TestInteractorSetting(mitk::DataNode::Pointer dataNode) { //this method tests the SetInteractor() and GetInteractor methods //the Interactor base class calls the DataNode->SetInteractor method mitk::Interactor::Pointer interactor; MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a NULL pointer was set correctly (Interactor)" ) interactor = mitk::AffineInteractor::New("AffineInteractions click to select", dataNode); dataNode->EnableInteractor(); dataNode->DisableInteractor(); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a AffineInteractor was set correctly" ) interactor = mitk::PointSetInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a PointSetInteractor was set correctly" ) } static void TestPropertyList(mitk::DataNode::Pointer dataNode) { mitk::PropertyList::Pointer propertyList = dataNode->GetPropertyList(); MITK_TEST_CONDITION(dataNode->GetPropertyList() != NULL, "Testing if the constructor set the propertylist" ) dataNode->SetIntProperty("int", -31337); int x; dataNode->GetIntProperty("int", x); MITK_TEST_CONDITION(x == -31337, "Testing Set/GetIntProperty"); dataNode->SetBoolProperty("bool", true); bool b; dataNode->GetBoolProperty("bool", b); MITK_TEST_CONDITION(b == true, "Testing Set/GetBoolProperty"); dataNode->SetFloatProperty("float", -31.337); float y; dataNode->GetFloatProperty("float", y); MITK_TEST_CONDITION(y - -31.337 < 0.01, "Testing Set/GetFloatProperty"); dataNode->SetStringProperty("string", "MITK"); std::string s = "GANZVIELPLATZ"; dataNode->GetStringProperty("string", s); MITK_TEST_CONDITION(s == "MITK", "Testing Set/GetStringProperty"); std::string name = "MyTestName"; dataNode->SetName(name.c_str()); MITK_TEST_CONDITION(dataNode->GetName() == name, "Testing Set/GetName"); name = "MySecondTestName"; dataNode->SetName(name); MITK_TEST_CONDITION(dataNode->GetName() == name, "Testing Set/GetName(std::string)"); MITK_TEST_CONDITION(propertyList == dataNode->GetPropertyList(), "Testing if the propertylist has changed during the last tests" ) } static void TestSelected(mitk::DataNode::Pointer dataNode) { vtkRenderWindow *renderWindow = vtkRenderWindow::New(); mitk::VtkPropRenderer::Pointer base = mitk::VtkPropRenderer::New( "the first renderer", renderWindow, mitk::RenderingManager::GetInstance() ); //with BaseRenderer==Null MITK_TEST_CONDITION(!dataNode->IsSelected(), "Testing if this node is not set as selected" ) dataNode->SetSelected(true); MITK_TEST_CONDITION(dataNode->IsSelected(), "Testing if this node is set as selected" ) dataNode->SetSelected(false); dataNode->SetSelected(true,base); MITK_TEST_CONDITION(dataNode->IsSelected(base), "Testing if this node with right base renderer is set as selected" ) //Delete RenderWindow correctly renderWindow->Delete(); } static void TestGetMTime(mitk::DataNode::Pointer dataNode) { unsigned long time; time = dataNode->GetMTime(); mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); dataNode->SetData(pointSet); MITK_TEST_CONDITION( time != dataNode->GetMTime(), "Testing if the node timestamp is updated after adding data to the node" ) mitk::Point3D point; point.Fill(3.0); pointSet->SetPoint(0,point); //less or equal because dataNode timestamp is little later then the basedata timestamp MITK_TEST_CONDITION( pointSet->GetMTime() <= dataNode->GetMTime(), "Testing if the node timestamp is updated after base data was modified" ) // testing if changing anything in the property list also sets the node in a modified state unsigned long lastModified = dataNode->GetMTime(); dataNode->SetIntProperty("testIntProp", 2344); MITK_TEST_CONDITION( lastModified <= dataNode->GetMTime(), "Testing if the node timestamp is updated after property list was modified" ) } }; //mitkDataNodeTestClass int mitkDataNodeTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("DataNode") // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); // let's create an object of our class mitk::DataNode::Pointer myDataNode = mitk::DataNode::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(myDataNode.IsNotNull(),"Testing instantiation") //test setData() Method mitkDataNodeTestClass::TestDataSetting(myDataNode); mitkDataNodeTestClass::TestMapperSetting(myDataNode); // //note, that no data is set to the dataNode mitkDataNodeTestClass::TestInteractorSetting(myDataNode); mitkDataNodeTestClass::TestPropertyList(myDataNode); mitkDataNodeTestClass::TestSelected(myDataNode); mitkDataNodeTestClass::TestGetMTime(myDataNode); // write your own tests here and use the macros from mitkTestingMacros.h !!! // do not write to std::cout and do not return from this function yourself! // always end with this! MITK_TEST_END() } diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake index 7329086108..b17a9bd424 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,324 +1,324 @@ SET(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkLocalVariationImageFilter.h Algorithms/itkLocalVariationImageFilter.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/itkTotalVariationDenoisingImageFilter.h Algorithms/itkTotalVariationDenoisingImageFilter.txx Algorithms/itkTotalVariationSingleIterationImageFilter.h Algorithms/itkTotalVariationSingleIterationImageFilter.txx Algorithms/mitkImageAccessByItk.h Algorithms/mitkImageCast.h Algorithms/mitkImageToItk.h Algorithms/mitkImageToItk.txx Algorithms/mitkInstantiateAccessFunctions.h Algorithms/mitkITKImageImport.h Algorithms/mitkITKImageImport.txx Algorithms/mitkPixelTypeList.h # Preprocessor macros taken from Boost Algorithms/mitkPPArithmeticDec.h Algorithms/mitkPPArgCount.h Algorithms/mitkPPCat.h Algorithms/mitkPPConfig.h Algorithms/mitkPPControlExprIIf.h Algorithms/mitkPPControlIf.h Algorithms/mitkPPControlIIf.h Algorithms/mitkPPDebugError.h Algorithms/mitkPPDetailAutoRec.h Algorithms/mitkPPDetailDMCAutoRec.h Algorithms/mitkPPExpand.h Algorithms/mitkPPFacilitiesEmpty.h Algorithms/mitkPPFacilitiesExpand.h Algorithms/mitkPPLogicalBool.h Algorithms/mitkPPRepetitionDetailDMCFor.h Algorithms/mitkPPRepetitionDetailEDGFor.h Algorithms/mitkPPRepetitionDetailFor.h Algorithms/mitkPPRepetitionDetailMSVCFor.h Algorithms/mitkPPRepetitionFor.h Algorithms/mitkPPSeqElem.h Algorithms/mitkPPSeqForEach.h Algorithms/mitkPPSeqForEachProduct.h Algorithms/mitkPPSeq.h Algorithms/mitkPPSeqEnum.h Algorithms/mitkPPSeqSize.h Algorithms/mitkPPSeqToTuple.h Algorithms/mitkPPStringize.h Algorithms/mitkPPTupleEat.h Algorithms/mitkPPTupleElem.h Algorithms/mitkPPTupleRem.h Algorithms/mitkClippedSurfaceBoundsCalculator.h DataManagement/mitkCommon.h Interactions/mitkEventMapperAddOn.h Service/mitkAny.h Service/mitkGetModuleContext.h Service/mitkItkHashMap.h Service/mitkItkHashSet.h Service/mitkItkHashTable.h Service/mitkModuleAbstractTracked.h Service/mitkModuleAbstractTracked.tpp Service/mitkModuleActivator.h Service/mitkServiceFactory.h Service/mitkServiceTracker.h Service/mitkServiceTracker.tpp Service/mitkServiceTrackerCustomizer.h Service/mitkServiceTrackerPrivate.h Service/mitkServiceTrackerPrivate.tpp Service/mitkServiceUtils.h Service/mitkSharedData.h Service/mitkStaticInit.h Service/mitkTrackedService.h Service/mitkTrackedService.tpp Service/mitkTrackedServiceListener.h ) SET(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkBaseProcess.cpp Algorithms/mitkCoreObjectFactoryBase.cpp Algorithms/mitkCoreObjectFactory.cpp Algorithms/mitkDataNodeFactory.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageCaster.cpp Algorithms/mitkImageCastPart1.cpp Algorithms/mitkImageCastPart2.cpp Algorithms/mitkImageCastPart3.cpp Algorithms/mitkImageCastPart4.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkFocusManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkSlicesRotator.cpp Controllers/mitkSlicesSwiveller.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkInteractorCameraController.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataStorage.cpp #DataManagement/mitkDataTree.cpp DataManagement/mitkDataNode.cpp #DataManagement/mitkDataTreeStorage.cpp DataManagement/mitkDisplayGeometry.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkGeometry2D.cpp DataManagement/mitkGeometry2DData.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkLandmarkBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModeOperation.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStateTransitionOperation.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeSlicedGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkVector.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkShaderProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkMaterial.cpp Interactions/mitkAction.cpp Interactions/mitkAffineInteractor.cpp Interactions/mitkCoordinateSupplier.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkDisplayPositionEvent.cpp Interactions/mitkDisplayVectorInteractor.cpp Interactions/mitkDisplayVectorInteractorLevelWindow.cpp Interactions/mitkDisplayVectorInteractorScroll.cpp Interactions/mitkEvent.cpp Interactions/mitkEventDescription.cpp Interactions/mitkEventMapper.cpp Interactions/mitkGlobalInteraction.cpp Interactions/mitkInteractor.cpp Interactions/mitkMouseMovePointSetInteractor.cpp Interactions/mitkMoveSurfaceInteractor.cpp Interactions/mitkNodeDepententPointSetInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Interactions/mitkState.cpp Interactions/mitkStateEvent.cpp Interactions/mitkStateMachine.cpp Interactions/mitkStateMachineFactory.cpp Interactions/mitkTransition.cpp Interactions/mitkWheelEvent.cpp Interactions/mitkKeyEvent.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkCrosshairPositionEvent.cpp IO/mitkBaseDataIOFactory.cpp IO/mitkDicomSeriesReader.cpp IO/mitkFileReader.cpp IO/mitkFileSeriesReader.cpp IO/mitkFileWriter.cpp IO/mitkIpPicGet.c IO/mitkImageGenerator.cpp IO/mitkImageWriter.cpp IO/mitkImageWriterFactory.cpp IO/mitkItkImageFileIOFactory.cpp IO/mitkItkImageFileReader.cpp IO/mitkItkPictureWrite.cpp IO/mitkLookupTableProperty.cpp IO/mitkOperation.cpp IO/mitkPicFileIOFactory.cpp IO/mitkPicFileReader.cpp IO/mitkPicFileWriter.cpp IO/mitkPicHelper.cpp IO/mitkPicVolumeTimeSeriesIOFactory.cpp IO/mitkPicVolumeTimeSeriesReader.cpp IO/mitkPixelType.cpp IO/mitkPointSetIOFactory.cpp IO/mitkPointSetReader.cpp IO/mitkPointSetWriter.cpp IO/mitkPointSetWriterFactory.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSTLFileIOFactory.cpp IO/mitkSTLFileReader.cpp IO/mitkSurfaceVtkWriter.cpp IO/mitkSurfaceVtkWriterFactory.cpp IO/mitkVtiFileIOFactory.cpp IO/mitkVtiFileReader.cpp IO/mitkVtkImageIOFactory.cpp IO/mitkVtkImageReader.cpp IO/mitkVtkSurfaceIOFactory.cpp IO/mitkVtkSurfaceReader.cpp IO/vtkPointSetXMLParser.cpp IO/mitkLog.cpp Rendering/mitkBaseRenderer.cpp Rendering/mitkVtkMapper2D.cpp Rendering/mitkVtkMapper3D.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkGeometry2DDataMapper2D.cpp Rendering/mitkGeometry2DDataVtkMapper3D.cpp Rendering/mitkGLMapper2D.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkManufacturerLogo.cpp Rendering/mitkMapper2D.cpp Rendering/mitkMapper3D.cpp Rendering/mitkMapper.cpp Rendering/mitkPointSetGLMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkPolyDataGLMapper2D.cpp Rendering/mitkSurfaceGLMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVolumeDataVtkMapper3D.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkShaderRepository.cpp - - Rendering/mitkImageMapperGL2D.cpp + Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp + Rendering/vtkMitkApplyLevelWindowToRGBFilter.cpp Service/mitkAny.cpp Service/mitkAtomicInt.cpp Service/mitkCoreActivator.cpp Service/mitkCoreModuleContext.cpp Service/mitkModule.cpp Service/mitkModuleContext.cpp Service/mitkModuleEvent.cpp Service/mitkModuleInfo.cpp Service/mitkModulePrivate.cpp Service/mitkModuleRegistry.cpp Service/mitkModuleUtils.cpp Service/mitkModuleVersion.cpp Service/mitkLDAPExpr.cpp Service/mitkLDAPFilter.cpp Service/mitkServiceEvent.cpp Service/mitkServiceException.cpp Service/mitkServiceListenerEntry.cpp Service/mitkServiceListeners.cpp Service/mitkServiceProperties.cpp Service/mitkServiceReference.cpp Service/mitkServiceReferencePrivate.cpp Service/mitkServiceRegistration.cpp Service/mitkServiceRegistrationPrivate.cpp Service/mitkServiceRegistry.cpp ) diff --git a/CoreUI/Qmitk/QmitkRenderWindow.cpp b/CoreUI/Qmitk/QmitkRenderWindow.cpp index cbf299e93c..99d12b6c83 100644 --- a/CoreUI/Qmitk/QmitkRenderWindow.cpp +++ b/CoreUI/Qmitk/QmitkRenderWindow.cpp @@ -1,270 +1,278 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "QmitkRenderWindow.h" #include #include #include #include #include #include #include "QmitkEventAdapter.h" #include "QmitkRenderWindowMenu.h" QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, QString name, mitk::VtkPropRenderer* /*renderer*/, mitk::RenderingManager* renderingManager ) : QVTKWidget(parent) , m_ResendQtEvents(true) , m_MenuWidget(NULL) , m_MenuWidgetActivated(false) , m_LayoutIndex(0) { Initialize( renderingManager, name.toStdString().c_str() ); // Initialize mitkRenderWindowBase setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); } QmitkRenderWindow::~QmitkRenderWindow() { Destroy(); // Destroy mitkRenderWindowBase } void QmitkRenderWindow::SetResendQtEvents(bool resend) { m_ResendQtEvents = resend; } void QmitkRenderWindow::SetLayoutIndex( unsigned int layoutIndex ) { m_LayoutIndex = layoutIndex; if( m_MenuWidget ) m_MenuWidget->SetLayoutIndex(layoutIndex); } unsigned int QmitkRenderWindow::GetLayoutIndex() { if( m_MenuWidget ) return m_MenuWidget->GetLayoutIndex(); else return NULL; } void QmitkRenderWindow::LayoutDesignListChanged( int layoutDesignIndex ) { if( m_MenuWidget ) m_MenuWidget->UpdateLayoutDesignList( layoutDesignIndex ); } void QmitkRenderWindow::mousePressEvent(QMouseEvent *me) { mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mousePressMitkEvent(&myevent); QVTKWidget::mousePressEvent(me); if (m_ResendQtEvents) me->ignore(); } void QmitkRenderWindow::mouseReleaseEvent(QMouseEvent *me) { mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mouseReleaseMitkEvent(&myevent); QVTKWidget::mouseReleaseEvent(me); if (m_ResendQtEvents) me->ignore(); } void QmitkRenderWindow::mouseMoveEvent(QMouseEvent *me) { this->AdjustRenderWindowMenuVisibility( me->pos() ); mitk::MouseEvent myevent(QmitkEventAdapter::AdaptMouseEvent(m_Renderer, me)); this->mouseMoveMitkEvent(&myevent); QVTKWidget::mouseMoveEvent(me); //if (m_ResendQtEvents) me->ignore(); ////Show/Hide Menu Widget //if( m_MenuWidgetActivated ) //{ // //Show Menu Widget when mouse is inside of the define region of the top right corner // if( m_MenuWidget->GetLayoutIndex() <= QmitkRenderWindowMenu::CORONAL // && me->pos().x() >= 0 // && me->pos().y() <= m_MenuWidget->height() + 20 ) // { // m_MenuWidget->MoveWidgetToCorrectPos(1.0); // m_MenuWidget->show(); // m_MenuWidget->update(); // } // else if( m_MenuWidget->GetLayoutIndex() == QmitkRenderWindowMenu::THREE_D // && me->pos().x() >= this->width() - m_MenuWidget->width() - 20 // && me->pos().y() <= m_MenuWidget->height() + 20 ) // { // m_MenuWidget->MoveWidgetToCorrectPos(1.0); // m_MenuWidget->show(); // m_MenuWidget->update(); // } // //Hide Menu Widget when mouse is outside of the define region of the the right corner // else if( !m_MenuWidget->GetSettingsMenuVisibilty() ) // { // m_MenuWidget->hide(); // } //} } void QmitkRenderWindow::wheelEvent(QWheelEvent *we) { mitk::WheelEvent myevent(QmitkEventAdapter::AdaptWheelEvent(m_Renderer, we)); this->wheelMitkEvent(&myevent); QVTKWidget::wheelEvent(we); if (m_ResendQtEvents) we->ignore(); } void QmitkRenderWindow::keyPressEvent(QKeyEvent *ke) { QPoint cp = mapFromGlobal(QCursor::pos()); mitk::KeyEvent mke(QmitkEventAdapter::AdaptKeyEvent(m_Renderer, ke, cp)); this->keyPressMitkEvent(&mke); ke->accept(); QVTKWidget::keyPressEvent(ke); if (m_ResendQtEvents) ke->ignore(); } void QmitkRenderWindow::enterEvent( QEvent *e ) { MITK_DEBUG << "rw enter Event"; QVTKWidget::enterEvent(e); } void QmitkRenderWindow::DeferredHideMenu( ) { MITK_DEBUG << "QmitkRenderWindow::DeferredHideMenu"; if( m_MenuWidget ) m_MenuWidget->HideMenu(); } void QmitkRenderWindow::leaveEvent( QEvent *e ) { MITK_DEBUG << "QmitkRenderWindow::leaveEvent"; if( m_MenuWidget ) m_MenuWidget->smoothHide(); QVTKWidget::leaveEvent(e); } +void QmitkRenderWindow::paintEvent(QPaintEvent* event) +{ + //Before the paint event is passed to Qt the VTK camera etc. has to be prepared. +// mitk::RenderingManager::GetInstance()->RequestUpdate(GetRenderWindow()); + GetRenderer()->PrepareRender(); + QVTKWidget::paintEvent(event); +} + void QmitkRenderWindow::resizeEvent(QResizeEvent* event) { this->resizeMitkEvent(event->size().width(), event->size().height()); QVTKWidget::resizeEvent(event); - + emit resized(); } void QmitkRenderWindow::moveEvent( QMoveEvent* event ) { QVTKWidget::moveEvent( event ); // after a move the overlays need to be positioned emit moved(); } void QmitkRenderWindow::showEvent( QShowEvent* event ) { QVTKWidget::showEvent( event ); // this singleshot is necessary to have the overlays positioned correctly after initial show // simple call of moved() is no use here!! QTimer::singleShot(0, this ,SIGNAL( moved() ) ); } void QmitkRenderWindow::ActivateMenuWidget( bool state ) { m_MenuWidgetActivated = state; if(!m_MenuWidgetActivated && m_MenuWidget) { //disconnect Signal/Slot Connection disconnect( m_MenuWidget, SIGNAL( SignalChangeLayoutDesign(int) ), this, SLOT(OnChangeLayoutDesign(int)) ); disconnect( m_MenuWidget, SIGNAL( ResetView() ), this, SIGNAL( ResetView()) ); disconnect( m_MenuWidget, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SIGNAL( ChangeCrosshairRotationMode(int)) ); delete m_MenuWidget; m_MenuWidget = 0; } else if(m_MenuWidgetActivated && !m_MenuWidget ) { //create render window MenuBar for split, close Window or set new setting. m_MenuWidget = new QmitkRenderWindowMenu(this,0,m_Renderer); m_MenuWidget->SetLayoutIndex( m_LayoutIndex ); //create Signal/Slot Connection connect( m_MenuWidget, SIGNAL( SignalChangeLayoutDesign(int) ), this, SLOT(OnChangeLayoutDesign(int)) ); connect( m_MenuWidget, SIGNAL( ResetView() ), this, SIGNAL( ResetView()) ); connect( m_MenuWidget, SIGNAL( ChangeCrosshairRotationMode(int) ), this, SIGNAL( ChangeCrosshairRotationMode(int)) ); } } void QmitkRenderWindow::AdjustRenderWindowMenuVisibility( const QPoint& pos ) { if( m_MenuWidget ) { m_MenuWidget->ShowMenu(); m_MenuWidget->MoveWidgetToCorrectPos(1.0f); } } void QmitkRenderWindow::HideRenderWindowMenu( ) { // DEPRECATED METHOD } void QmitkRenderWindow::OnChangeLayoutDesign( int layoutDesignIndex ) { emit SignalLayoutDesignChanged( layoutDesignIndex ); } void QmitkRenderWindow::OnWidgetPlaneModeChanged( int mode ) { if( m_MenuWidget ) m_MenuWidget->NotifyNewWidgetPlanesMode( mode ); } void QmitkRenderWindow::FullScreenMode(bool state) { if( m_MenuWidget ) m_MenuWidget->ChangeFullScreenMode( state ); } diff --git a/CoreUI/Qmitk/QmitkRenderWindow.h b/CoreUI/Qmitk/QmitkRenderWindow.h index afa9e23277..fbca94c031 100644 --- a/CoreUI/Qmitk/QmitkRenderWindow.h +++ b/CoreUI/Qmitk/QmitkRenderWindow.h @@ -1,152 +1,148 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #define QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #include #include "mitkRenderWindowBase.h" #include "QVTKWidget.h" #include "QmitkRenderWindowMenu.h" /** * \brief MITK implementation of the QVTKWidget * \ingroup Renderer */ class QMITK_EXPORT QmitkRenderWindow : public QVTKWidget , public mitk::RenderWindowBase { Q_OBJECT public: QmitkRenderWindow(QWidget *parent = 0, QString name = "unnamed renderwindow", mitk::VtkPropRenderer* renderer = NULL, mitk::RenderingManager* renderingManager = NULL); virtual ~QmitkRenderWindow(); /** * \brief Whether Qt events should be passed to parent (default: true) * * With introduction of the QVTKWidget the behaviour regarding Qt events changed. * QVTKWidget "accepts" Qt events like mouse clicks (i.e. set an "accepted" flag). * When this flag is set, Qt fininshed handling of this event -- otherwise it is * reached through to the widget's parent. * * This reaching through to the parent was implicitly required by QmitkMaterialWidget / QmitkMaterialShowCase. * * The default behaviour of QmitkRenderWindow is now to clear the "accepted" flag * of Qt events after they were handled by QVTKWidget. This way parents can also * handle events. * * If you don't want this behaviour, call SetResendQtEvents(true) on your render window. */ virtual void SetResendQtEvents(bool resend); // Set Layout Index to define the Layout Type void SetLayoutIndex( unsigned int layoutIndex ); // Get Layout Index to define the Layout Type unsigned int GetLayoutIndex(); //MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged( int layoutDesignIndex ); void HideRenderWindowMenu( ); //Activate or Deactivate MenuWidget. void ActivateMenuWidget( bool state ); bool GetActivateMenuWidgetFlag() { return m_MenuWidgetActivated; } // Get it from the QVTKWidget parent virtual vtkRenderWindow* GetVtkRenderWindow() { return GetRenderWindow();} virtual vtkRenderWindowInteractor* GetVtkRenderWindowInteractor() { return NULL;} void FullScreenMode( bool state ); protected: - // overloaded move handler virtual void moveEvent( QMoveEvent* event ); - // overloaded show handler void showEvent( QShowEvent* event ); - - // overloaded resize handler virtual void resizeEvent(QResizeEvent* event); - + // overloaded paint handler + virtual void paintEvent(QPaintEvent* event); // overloaded mouse press handler virtual void mousePressEvent(QMouseEvent* event); // overloaded mouse move handler virtual void mouseMoveEvent(QMouseEvent* event); // overloaded mouse release handler virtual void mouseReleaseEvent(QMouseEvent* event); // overloaded key press handler virtual void keyPressEvent(QKeyEvent* event); - // overloaded enter handler virtual void enterEvent(QEvent*); // overloaded leave handler virtual void leaveEvent(QEvent*); #ifndef QT_NO_WHEELEVENT // overload wheel mouse event virtual void wheelEvent(QWheelEvent*); #endif void AdjustRenderWindowMenuVisibility( const QPoint& pos ); signals: void ResetView(); // \brief int parameters are enum from QmitkStdMultiWidget void ChangeCrosshairRotationMode(int); void SignalLayoutDesignChanged( int layoutDesignIndex ); void moved(); void resized(); protected slots: void OnChangeLayoutDesign(int layoutDesignIndex); void OnWidgetPlaneModeChanged( int ); void DeferredHideMenu(); private: bool m_ResendQtEvents; QmitkRenderWindowMenu* m_MenuWidget; bool m_MenuWidgetActivated; unsigned int m_LayoutIndex; }; #endif diff --git a/Documentation/Doxygen/ImageMapperdisplayGeometry.png b/Documentation/Doxygen/ImageMapperdisplayGeometry.png new file mode 100644 index 0000000000..504106d4d1 Binary files /dev/null and b/Documentation/Doxygen/ImageMapperdisplayGeometry.png differ diff --git a/Documentation/Doxygen/cameraPositioning.png b/Documentation/Doxygen/cameraPositioning.png new file mode 100644 index 0000000000..cfd2e25ee4 Binary files /dev/null and b/Documentation/Doxygen/cameraPositioning.png differ diff --git a/Documentation/Doxygen/cameraPositioning3D.png b/Documentation/Doxygen/cameraPositioning3D.png new file mode 100644 index 0000000000..2964ae7592 Binary files /dev/null and b/Documentation/Doxygen/cameraPositioning3D.png differ diff --git a/Documentation/Doxygen/imageVtkMapper2Darchitecture.png b/Documentation/Doxygen/imageVtkMapper2Darchitecture.png new file mode 100644 index 0000000000..50386c92e6 Binary files /dev/null and b/Documentation/Doxygen/imageVtkMapper2Darchitecture.png differ diff --git a/Documentation/Doxygen/scaling.png b/Documentation/Doxygen/scaling.png new file mode 100644 index 0000000000..701ad9c176 Binary files /dev/null and b/Documentation/Doxygen/scaling.png differ diff --git a/Documentation/Doxygen/texturedPlane.png b/Documentation/Doxygen/texturedPlane.png new file mode 100644 index 0000000000..0b6eb1e59b Binary files /dev/null and b/Documentation/Doxygen/texturedPlane.png differ diff --git a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx index cdce6d9559..747f20b8aa 100644 --- a/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx +++ b/Modules/DiffusionImaging/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx @@ -1,353 +1,353 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 11:19:03 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 11989 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "mitkImageCast.h" template mitk::DiffusionImage::DiffusionImage() : m_VectorImage(0), m_Directions(0), m_OriginalDirections(0), m_B_Value(-1.0), m_VectorImageAdaptor(0) { MeasurementFrameType mf; for(int i=0; i<3; i++) for(int j=0; j<3; j++) mf[i][j] = 0; for(int i=0; i<3; i++) mf[i][i] = 1; m_MeasurementFrame = mf; } template mitk::DiffusionImage::~DiffusionImage() { } template void mitk::DiffusionImage ::InitializeFromVectorImage() { if(!m_VectorImage || !m_Directions || m_B_Value==-1.0) { MITK_INFO << "DiffusionImage could not be initialized. Set all members first!" << std::endl; return; } // find bzero index int firstZeroIndex = -1; for(GradientDirectionContainerType::ConstIterator it = m_Directions->Begin(); it != m_Directions->End(); ++it) { firstZeroIndex++; GradientDirectionType g = it.Value(); if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) break; } typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); img->SetSpacing( m_VectorImage->GetSpacing() ); // Set the image spacing img->SetOrigin( m_VectorImage->GetOrigin() ); // Set the image origin img->SetDirection( m_VectorImage->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( m_VectorImage->GetLargestPossibleRegion()); img->SetBufferedRegion( m_VectorImage->GetLargestPossibleRegion() ); img->Allocate(); int vecLength = m_VectorImage->GetVectorLength(); InitializeByItk( img.GetPointer(), 1, vecLength ); //for(int i=0; i itw (img, img->GetLargestPossibleRegion() ); itw = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(firstZeroIndex)); ++itr; ++itw; } // init SetImportVolume(img->GetBufferPointer());//, 0, 0, CopyMemory); //SetVolume( img->GetBufferPointer(), i ); //} m_DisplayIndex = firstZeroIndex; MITK_INFO << "Diffusion-Image successfully initialized."; } template void mitk::DiffusionImage ::SetDisplayIndexForRendering(int displayIndex) { - +MITK_INFO << "ALOHA WE JUST RECEIVED A NEW INDEX FROM THE PROPERTIES IN MITK........................" << displayIndex; int index = displayIndex; int vecLength = m_VectorImage->GetVectorLength(); index = index > vecLength-1 ? vecLength-1 : index; if( m_DisplayIndex != index ) { typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); CastToItkImage(this, img); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(index)); ++itr; ++itw; } } m_DisplayIndex = index; } //template //bool mitk::DiffusionImage::RequestedRegionIsOutsideOfTheBufferedRegion() //{ // return false; //} // //template //void mitk::DiffusionImage::SetRequestedRegion(itk::DataObject * /*data*/) //{ //} // //template //void mitk::DiffusionImage::SetRequestedRegionToLargestPossibleRegion() //{ //} // //template //bool mitk::DiffusionImage::VerifyRequestedRegion() //{ // return true; //} //template //void mitk::DiffusionImage::DuplicateIfSingleSlice() //{ // // new image // typename ImageType::Pointer oldImage = m_Image; // m_Image = ImageType::New(); // m_Image->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing // m_Image->SetOrigin( oldImage->GetOrigin() ); // Set the image origin // m_Image->SetDirection( oldImage->GetDirection() ); // Set the image direction // typename ImageType::RegionType region = oldImage->GetLargestPossibleRegion(); // if(region.GetSize(0) == 1) // region.SetSize(0,3); // if(region.GetSize(1) == 1) // region.SetSize(1,3); // if(region.GetSize(2) == 1) // region.SetSize(2,3); // m_Image->SetLargestPossibleRegion( region ); // m_Image->SetVectorLength( m_Directions->size() ); // m_Image->SetBufferedRegion( region ); // m_Image->Allocate(); // // // average image data that corresponds to identical directions // itk::ImageRegionIterator< ImageType > newIt(m_Image, region); // newIt.GoToBegin(); // itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); // oldIt.GoToBegin(); // // while(!newIt.IsAtEnd()) // { // newIt.Set(oldIt.Get()); // ++newIt; // ++oldIt; // if(oldIt.IsAtEnd()) // oldIt.GoToBegin(); // } // //} template bool mitk::DiffusionImage::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision) { GradientDirectionType diff = g1 - g2; return diff.two_norm() < precision; } template void mitk::DiffusionImage::CorrectDKFZBrokenGradientScheme(double precision) { GradientDirectionContainerType::Pointer directionSet = CalcAveragedDirectionSet(precision, m_Directions); if(directionSet->size() < 7) { MITK_INFO << "Too few directions, assuming and correcting DKFZ-bogus sequence details."; double v [7][3] = {{ 0, 0, 0 }, {-0.707057, 0, 0.707057 }, { 0.707057, 0, 0.707057 }, { 0, 0.707057, 0.707057 }, { 0, 0.707057, -0.707057 }, {-0.707057, 0.707057, 0 }, { 0.707057, 0.707057, 0 } }; int i=0; for(GradientDirectionContainerType::Iterator it = m_Directions->Begin(); it != m_Directions->End(); ++it) { it.Value().set(v[i++%7]); } for(GradientDirectionContainerType::Iterator it = m_OriginalDirections->Begin(); it != m_OriginalDirections->End(); ++it) { it.Value().set(v[i++%7]); } } } template mitk::DiffusionImage::GradientDirectionContainerType::Pointer mitk::DiffusionImage::CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionContainerType::Pointer newDirections = GradientDirectionContainerType::New(); // fill new direction container for(GradientDirectionContainerType::ConstIterator gdcitOld = directions->Begin(); gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionContainerType::ConstIterator gdcitNew = newDirections->Begin(); gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } template void mitk::DiffusionImage::AverageRedundantGradients(double precision) { GradientDirectionContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, m_Directions); GradientDirectionContainerType::Pointer newOriginalDirs = CalcAveragedDirectionSet(precision, m_OriginalDirections); // if sizes equal, we do not need to do anything in this function if(m_Directions->size() == newDirs->size() || m_OriginalDirections->size() == newOriginalDirs->size()) return; GradientDirectionContainerType::Pointer oldDirections = m_Directions; GradientDirectionContainerType::Pointer oldOriginalDirections = m_OriginalDirections; m_Directions = newDirs; m_OriginalDirections = newOriginalDirs; // new image typename ImageType::Pointer oldImage = m_VectorImage; m_VectorImage = ImageType::New(); m_VectorImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing m_VectorImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin m_VectorImage->SetDirection( oldImage->GetDirection() ); // Set the image direction m_VectorImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->SetVectorLength( m_Directions->size() ); m_VectorImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(m_VectorImage, m_VectorImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel typename ImageType::PixelType newVec; newVec.SetSize(m_Directions->size()); newVec.AllocateElements(m_Directions->size()); std::vector > dirIndices; for(GradientDirectionContainerType::ConstIterator gdcitNew = m_Directions->Begin(); gdcitNew != m_Directions->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionContainerType::ConstIterator gdcitOld = oldDirections->Begin(); gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } int ind1 = -1; while(!newIt.IsAtEnd()) { // progress typename ImageType::IndexType ind = newIt.GetIndex(); ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates typename ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; i DiffusionImageShort; typedef std::multimap MultimapType; mitk::DiffusionImagingObjectFactory::DiffusionImagingObjectFactory(bool /*registerSelf*/) :CoreObjectFactoryBase() { static bool alreadyDone = false; if (!alreadyDone) { MITK_INFO << "DiffusionImagingObjectFactory c'tor" << std::endl; RegisterIOFactories(); mitk::NrrdDiffusionImageIOFactory::RegisterOneFactory(); mitk::NrrdQBallImageIOFactory::RegisterOneFactory(); mitk::NrrdTensorImageIOFactory::RegisterOneFactory(); mitk::FiberBundleIOFactory::RegisterOneFactory(); mitk::NrrdTbssImageIOFactory::RegisterOneFactory(); mitk::FiberBundleXIOFactory::RegisterOneFactory(); //modernized mitk::NrrdDiffusionImageWriterFactory::RegisterOneFactory(); mitk::NrrdQBallImageWriterFactory::RegisterOneFactory(); mitk::NrrdTensorImageWriterFactory::RegisterOneFactory(); mitk::FiberBundleWriterFactory::RegisterOneFactory(); mitk::NrrdTbssImageWriterFactory::RegisterOneFactory(); mitk::FiberBundleXWriterFactory::RegisterOneFactory();//modernized m_FileWriters.push_back( NrrdDiffusionImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdQBallImageWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdTensorImageWriter::New().GetPointer() ); m_FileWriters.push_back( mitk::FiberBundleWriter::New().GetPointer() ); m_FileWriters.push_back( NrrdTbssImageWriter::New().GetPointer() ); m_FileWriters.push_back( mitk::FiberBundleXWriter::New().GetPointer() );//modernized mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(this); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::Mapper::Pointer mitk::DiffusionImagingObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id) { mitk::Mapper::Pointer newMapper=NULL; if ( id == mitk::BaseRenderer::Standard2D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::CompositeMapper::New(); newMapper->SetDataNode(node); node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper()); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::DiffusionImageMapper::New(); newMapper->SetDataNode(node); } mitk::Mapper::Pointer newMapper=NULL; classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { - newMapper = mitk::ImageMapperGL2D::New(); + newMapper = mitk::ImageVtkMapper2D::New(); newMapper->SetDataNode(node); } } else if ( id == mitk::BaseRenderer::Standard3D ) { std::string classname("QBallImage"); if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::GPUVolumeMapper3D::New(); newMapper->SetDataNode(node); } classname = "FiberBundle"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleMapper3D::New(); newMapper->SetDataNode(node); } classname = "FiberBundleX"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXMapper3D::New(); newMapper->SetDataNode(node); } classname = "FiberBundleXThreadMonitor"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::FiberBundleXThreadMonitorMapper3D::New(); newMapper->SetDataNode(node); } classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { newMapper = mitk::VolumeDataVtkMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::DiffusionImagingObjectFactory::SetDefaultProperties(mitk::DataNode* node) { std::string classname = "QBallImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "TensorImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::CompositeMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "DiffusionImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::DiffusionImageMapper::SetDefaultProperties(node); mitk::GPUVolumeMapper3D::SetDefaultProperties(node); } classname = "FiberBundle"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleMapper3D::SetDefaultProperties(node); } classname = "FiberBundleX"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleXMapper3D::SetDefaultProperties(node); } classname = "FiberBundleXThreadMonitor"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { mitk::FiberBundleXThreadMonitorMapper3D::SetDefaultProperties(node); } classname = "TbssImage"; if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0) { - mitk::ImageMapperGL2D::SetDefaultProperties(node); + mitk::ImageVtkMapper2D::SetDefaultProperties(node); mitk::VolumeDataVtkMapper3D::SetDefaultProperties(node); } } const char* mitk::DiffusionImagingObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionImagingObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } const char* mitk::DiffusionImagingObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); }; mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionImagingObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::DiffusionImagingObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.dwi", "Diffusion Weighted Images")); m_FileExtensionsMap.insert(std::pair("*.hdwi", "Diffusion Weighted Images")); m_FileExtensionsMap.insert(std::pair("*.nii", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.fsl", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.fslgz", "Diffusion Weighted Images for FSL")); m_FileExtensionsMap.insert(std::pair("*.qbi", "Q-Ball Images")); m_FileExtensionsMap.insert(std::pair("*.hqbi", "Q-Ball Images")); m_FileExtensionsMap.insert(std::pair("*.dti", "Tensor Images")); m_FileExtensionsMap.insert(std::pair("*.hdti", "Tensor Images")); m_FileExtensionsMap.insert(std::pair("*.fib", "Fiber Bundle")); m_FileExtensionsMap.insert(std::pair("*.vfib", "Fiber Bundle Polydata")); m_FileExtensionsMap.insert(std::pair("*.vtk", "Fiber Bundle Polydata")); m_FileExtensionsMap.insert(std::pair("*.tbss", "TBSS data")); m_SaveFileExtensionsMap.insert(std::pair("*.dwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hdwi", "Diffusion Weighted Images")); m_SaveFileExtensionsMap.insert(std::pair("*.nii", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.fsl", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.fslgz", "Diffusion Weighted Images for FSL")); m_SaveFileExtensionsMap.insert(std::pair("*.qbi", "Q-Ball Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hqbi", "Q-Ball Images")); m_SaveFileExtensionsMap.insert(std::pair("*.dti", "Tensor Images")); m_SaveFileExtensionsMap.insert(std::pair("*.hdti", "Tensor Images")); m_SaveFileExtensionsMap.insert(std::pair("*.fib", "Fiber Bundle")); m_SaveFileExtensionsMap.insert(std::pair("*.vfib", "Fiber Bundle Polydata")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "Fiber Bundle Polydata")); m_SaveFileExtensionsMap.insert(std::pair("*.tbss", "TBSS data")); } void mitk::DiffusionImagingObjectFactory::RegisterIOFactories() { } void RegisterDiffusionImagingObjectFactory() { static bool oneDiffusionImagingObjectFactoryRegistered = false; if ( ! oneDiffusionImagingObjectFactoryRegistered ) { MITK_INFO << "Registering DiffusionImagingObjectFactory..." << std::endl; mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(mitk::DiffusionImagingObjectFactory::New()); oneDiffusionImagingObjectFactoryRegistered = true; } } diff --git a/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.cpp b/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.cpp index 68a8700d23..76dbbefeca 100644 --- a/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.cpp @@ -1,70 +1,31 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkCompositeMapper.h" mitk::CompositeMapper::CompositeMapper() { m_OdfMapper = mitk::OdfVtkMapper2D::New(); m_ImgMapper = mitk::CopyImageMapper2D::New(); } mitk::CompositeMapper::~CompositeMapper() { } - -void mitk::CompositeMapper::Enable2DOpenGL() -{ - GLint iViewport[4]; - - // Get a copy of the viewport - glGetIntegerv( GL_VIEWPORT, iViewport ); - - // Save a copy of the projection matrix so that we can restore it - // when it's time to do 3D rendering again. - glMatrixMode( GL_PROJECTION ); - glPushMatrix(); - glLoadIdentity(); - - // Set up the orthographic projection - glOrtho( - iViewport[0], iViewport[0]+iViewport[2], - iViewport[1], iViewport[1]+iViewport[3], - -1.0, 1.0 - ); - glMatrixMode( GL_MODELVIEW ); - glPushMatrix(); - glLoadIdentity(); - - // Make sure depth testing and lighting are disabled for 2D rendering until - // we are finished rendering in 2D - glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_LIGHTING ); -} - -void mitk::CompositeMapper::Disable2DOpenGL() -{ - glPopAttrib(); - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); -} diff --git a/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.h b/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.h index 7b21c508bd..f99682ab50 100644 --- a/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.h +++ b/Modules/DiffusionImaging/Rendering/mitkCompositeMapper.h @@ -1,178 +1,170 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef COMPOSITEMAPPER_H_HEADER_INCLUDED #define COMPOSITEMAPPER_H_HEADER_INCLUDED #include "mitkGLMapper2D.h" #include "mitkVtkMapper2D.h" #include "mitkQBallImage.h" -#include "mitkImageMapperGL2D.h" +#include "mitkImageVtkMapper2D.h" #include "mitkOdfVtkMapper2D.h" #include "mitkLevelWindowProperty.h" namespace mitk { - class CopyImageMapper2D : public ImageMapperGL2D + class CopyImageMapper2D : public ImageVtkMapper2D { public: - mitkClassMacro(CopyImageMapper2D,ImageMapperGL2D); + mitkClassMacro(CopyImageMapper2D,ImageVtkMapper2D); itkNewMacro(Self); friend class CompositeMapper; }; //##Documentation //## @brief Composite pattern for combination of different mappers //## @ingroup Mapper class CompositeMapper : public VtkMapper2D { public: mitkClassMacro(CompositeMapper,VtkMapper2D); itkNewMacro(Self); virtual void MitkRenderOverlay(BaseRenderer* renderer) { - Enable2DOpenGL(); m_ImgMapper->MitkRenderOverlay(renderer); - Disable2DOpenGL(); m_OdfMapper->MitkRenderOverlay(renderer); } virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer) { - Enable2DOpenGL(); m_ImgMapper->MitkRenderOpaqueGeometry(renderer); - Disable2DOpenGL(); m_OdfMapper->MitkRenderOpaqueGeometry(renderer); if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 ) { renderer->Modified(); } } virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer) { - Enable2DOpenGL(); m_ImgMapper->MitkRenderTranslucentGeometry(renderer); - Disable2DOpenGL(); m_OdfMapper->MitkRenderTranslucentGeometry(renderer); } virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer) { - Enable2DOpenGL(); m_ImgMapper->MitkRenderVolumetricGeometry(renderer); - Disable2DOpenGL(); m_OdfMapper->MitkRenderVolumetricGeometry(renderer); } void SetDataNode(DataNode* node) { m_DataNode = node; m_ImgMapper->SetDataNode(node); m_OdfMapper->SetDataNode(node); } - mitk::ImageMapperGL2D::Pointer GetImageMapper() + mitk::ImageVtkMapper2D::Pointer GetImageMapper() { - ImageMapperGL2D* retval = m_ImgMapper; + ImageVtkMapper2D* retval = m_ImgMapper; return retval; } bool IsVtkBased() const { return m_OdfMapper->IsVtkBased(); } bool HasVtkProp( const vtkProp* prop, BaseRenderer* renderer ) { return m_OdfMapper->HasVtkProp(prop, renderer); } void ReleaseGraphicsResources(vtkWindow* window) { m_ImgMapper->ReleaseGraphicsResources(window); m_OdfMapper->ReleaseGraphicsResources(window); } static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ) { mitk::OdfVtkMapper2D::SetDefaultProperties(node, renderer, overwrite); mitk::CopyImageMapper2D::SetDefaultProperties(node, renderer, overwrite); mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,0); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->AddProperty( "opaclevelwindow", prop ); } bool IsLODEnabled( BaseRenderer * renderer ) const { return m_ImgMapper->IsLODEnabled(renderer) || m_OdfMapper->IsLODEnabled(renderer); } - vtkProp* GetProp(mitk::BaseRenderer* renderer) + vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) { - return m_OdfMapper->GetProp(renderer); + vtkPropAssembly* assembly = vtkPropAssembly::New(); + assembly->AddPart( m_OdfMapper->GetVtkProp(renderer)); + assembly->AddPart( m_ImgMapper->GetVtkProp(renderer)); + return assembly; } void SetGeometry3D(const mitk::Geometry3D* aGeometry3D) { m_ImgMapper->SetGeometry3D(aGeometry3D); m_OdfMapper->SetGeometry3D(aGeometry3D); } - void Enable2DOpenGL(); - void Disable2DOpenGL(); - protected: virtual void GenerateData() { m_OdfMapper->GenerateData(); } virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer) { m_ImgMapper->GenerateDataForRenderer(renderer); if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) > 0 ) { m_OdfMapper->GenerateDataForRenderer(renderer); } } CompositeMapper(); virtual ~CompositeMapper(); private: mitk::OdfVtkMapper2D::Pointer m_OdfMapper; mitk::CopyImageMapper2D::Pointer m_ImgMapper; }; } // namespace mitk #endif /* COMPOSITEMAPPER_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.cpp b/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.cpp index f6e801181f..4af1bf21f0 100644 --- a/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.cpp +++ b/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.cpp @@ -1,65 +1,65 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef DiffusionImageMapper_txx_HEADER_INCLUDED #define DiffusionImageMapper_txx_HEADER_INCLUDED #include "mitkProperties.h" #include "mitkDiffusionImage.h" template mitk::DiffusionImageMapper::DiffusionImageMapper() { } template mitk::DiffusionImageMapper::~DiffusionImageMapper() { } template void mitk::DiffusionImageMapper::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { int displayIndex(0); this->GetDataNode()->GetIntProperty( "DisplayChannel", displayIndex, renderer ); - InputImageType *input = const_cast< InputImageType* >( + mitk::Image *input = const_cast< mitk::Image* >( this->GetInput() ); mitk::DiffusionImage *input2 = dynamic_cast< mitk::DiffusionImage* >( input ); MITK_INFO << "displayindex: " << displayIndex; input2->SetDisplayIndexForRendering(displayIndex); Superclass::GenerateDataForRenderer(renderer); } template void mitk::DiffusionImageMapper::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "DisplayChannel", mitk::IntProperty::New( 0 ), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } #endif diff --git a/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.h b/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.h index 63922b82bf..fcdf87d6cb 100644 --- a/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.h +++ b/Modules/DiffusionImaging/Rendering/mitkDiffusionImageMapper.h @@ -1,54 +1,54 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef DiffusionImageMapper_H_HEADER_INCLUDED #define DiffusionImageMapper_H_HEADER_INCLUDED -#include "mitkImageMapperGL2D.h" +#include "mitkImageVtkMapper2D.h" namespace mitk { //##Documentation //## @brief Mapper for raw diffusion weighted images //## @ingroup Mapper template - class DiffusionImageMapper : public ImageMapperGL2D + class DiffusionImageMapper : public ImageVtkMapper2D { public: - mitkClassMacro(DiffusionImageMapper,ImageMapperGL2D); + mitkClassMacro(DiffusionImageMapper,ImageVtkMapper2D); itkNewMacro(Self); void GenerateDataForRenderer( mitk::BaseRenderer *renderer ); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); protected: DiffusionImageMapper(); virtual ~DiffusionImageMapper(); }; } // namespace mitk #include "mitkDiffusionImageMapper.cpp" #endif /* COMPOSITEMAPPER_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h index d0a951f152..69eea3f4de 100644 --- a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h +++ b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.h @@ -1,154 +1,154 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-02-08 13:23:19 +0100 (Fr, 08 Feb 2008) $ Version: $Revision: 13561 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef ODFVTKMAPPER2D_H_HEADER_INCLUDED #define ODFVTKMAPPER2D_H_HEADER_INCLUDED #include "mitkVtkMapper2D.h" #include "vtkPropAssembly.h" #include "vtkAppendPolyData.h" #include "vtkActor.h" #include "vtkPolyDataMapper.h" #include "vtkPlane.h" #include "vtkCutter.h" #include "vtkClipPolyData.h" #include "vtkTransform.h" #include "vtkDataArrayTemplate.h" #include "vtkSmartPointer.h" #include "vtkOdfSource.h" #include "vtkThickPlane.h" //#include "mitkTrackingCameraController.h" namespace mitk { //##Documentation //## @brief Base class of all vtk-based 2D-Mappers //## //## Those must implement the abstract //## method vtkProp* GetProp(). //## @ingroup Mapper template class OdfVtkMapper2D : public VtkMapper2D { struct OdfDisplayGeometry { vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Vector3D normal; double d, d1, d2; mitk::Point3D M3D, L3D, O3D; vtkFloatingPointType vp_original[ 3 ], vnormal_original[ 3 ]; mitk::Vector2D size, origin; bool Equals(OdfDisplayGeometry* other) { return other->vp_original[0] == vp[0] && other->vp_original[1] == vp[1] && other->vp_original[2] == vp[2] && other->vnormal_original[0] == vnormal[0] && other->vnormal_original[1] == vnormal[1] && other->vnormal_original[2] == vnormal[2] && other->size[0] == size[0] && other->size[1] == size[1] && other->origin[0] == origin[0] && other->origin[1] == origin[1]; } }; public: mitkClassMacro(OdfVtkMapper2D,VtkMapper2D); itkNewMacro(Self); - virtual vtkProp* GetProp(mitk::BaseRenderer* renderer); + virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); bool IsVisibleOdfs(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(mitk::BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/){}; OdfDisplayGeometry* MeasureDisplayedGeometry(mitk::BaseRenderer* renderer); void AdaptCameraPosition(mitk::BaseRenderer* renderer, OdfDisplayGeometry* dispGeo ); void AdaptOdfScalingToImageSpacing( int index ); void SetRendererLightSources( mitk::BaseRenderer *renderer ); void ApplyPropertySettings(); virtual void Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry* dispGeo); virtual int GetIndex(mitk::BaseRenderer* renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); virtual void GenerateData(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return true; } protected: OdfVtkMapper2D(); virtual ~OdfVtkMapper2D(); static void GlyphMethod(void *arg); bool IsPlaneRotated(mitk::BaseRenderer* renderer); private: std::vector m_PropAssemblies; std::vector m_OdfsPlanes; std::vector m_OdfsActors; std::vector m_OdfsMappers; vtkPolyData* m_TemplateOdf; static vtkSmartPointer m_OdfTransform; static vtkSmartPointer m_OdfVals; static vtkSmartPointer m_OdfSource; static float m_Scaling; static int m_Normalization; static int m_ScaleBy; static float m_IndexParam1; static float m_IndexParam2; int m_ShowMaxNumber; //std::vector m_TrackingCameraControllers; std::vector m_Planes; std::vector m_Cutters; std::vector m_ThickPlanes1; std::vector m_Clippers1; std::vector m_ThickPlanes2; std::vector m_Clippers2; vtkImageData* m_VtkImage ; mitk::Image* GetInput(); OdfDisplayGeometry* m_LastDisplayGeometry; }; } // namespace mitk #include "mitkOdfVtkMapper2D.txx" #endif /* ODFVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx index dfe2fcdec4..3d5425c6bf 100644 --- a/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/Rendering/mitkOdfVtkMapper2D.txx @@ -1,1166 +1,1168 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-08-25 18:10:57 +0200 (Mo, 25 Aug 2008) $ Version: $Revision: 15062 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #ifndef __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfVals = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI 3.1415926535897932384626433832795 //#include "vtkSphereSource.h" //#include "vtkPolyDataMapper.h" //#include "vtkActor.h" //#include "vtkRenderWindow.h" //#include "vtkRenderer.h" //#include "vtkRenderWindowInteractor.h" //#include "vtkProperty.h" // //void bla(vtkPolyData* poly) //{ // // // map to graphics library // vtkPolyDataMapper *map = vtkPolyDataMapper::New(); // map->SetInput(poly); // // // actor coordinates geometry, properties, transformation // vtkActor *aSphere = vtkActor::New(); // aSphere->SetMapper(map); // aSphere->GetProperty()->SetColor(0,0,1); // sphere color blue // // // a renderer and render window // vtkRenderer *ren1 = vtkRenderer::New(); // vtkRenderWindow *renWin = vtkRenderWindow::New(); // renWin->AddRenderer(ren1); // // // an interactor // vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); // iren->SetRenderWindow(renWin); // // // add the actor to the scene // ren1->AddActor(aSphere); // ren1->SetBackground(1,1,1); // Background color white // // // render an image (lights and cameras are created automatically) // renWin->Render(); // // // begin mouse interaction // iren->Start(); //} template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_LastDisplayGeometry = 0; m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInput(vtkPolyData::New()); m_OdfsPlanes[1]->AddInput(vtkPolyData::New()); m_OdfsPlanes[2]->AddInput(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); //lut->SetMinimumTableValue(0,0,1,1); //lut->SetMaximumTableValue(1,0,0,1); //lut->SetWindow(0.1); //lut->SetLevel(0.05); <== not recognized or reset by mapper ?? //lut->Build(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); //vtkPoints* points = m_TemplateOdf->GetPoints(); m_OdfVals->Allocate(N); m_OdfSource->SetTemplateOdf(m_TemplateOdf); m_OdfSource->SetOdfVals(m_OdfVals); m_ShowMaxNumber = 500; //vtkMapper::GlobalImmediateModeRenderingOn(); } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { m_PropAssemblies[0]->Delete(); m_PropAssemblies[1]->Delete(); m_PropAssemblies[2]->Delete(); m_OdfsPlanes[0]->Delete(); m_OdfsPlanes[1]->Delete(); m_OdfsPlanes[2]->Delete(); m_OdfsActors[0]->Delete(); m_OdfsActors[1]->Delete(); m_OdfsActors[2]->Delete(); m_OdfsMappers[0]->Delete(); m_OdfsMappers[1]->Delete(); m_OdfsMappers[2]->Delete(); m_Planes[0]->Delete(); m_Planes[1]->Delete(); m_Planes[2]->Delete(); m_Cutters[0]->Delete(); m_Cutters[1]->Delete(); m_Cutters[2]->Delete(); m_ThickPlanes1[0]->Delete(); m_ThickPlanes1[1]->Delete(); m_ThickPlanes1[2]->Delete(); m_ThickPlanes2[0]->Delete(); m_ThickPlanes2[1]->Delete(); m_ThickPlanes2[2]->Delete(); m_Clippers1[0]->Delete(); m_Clippers1[1]->Delete(); m_Clippers1[2]->Delete(); m_Clippers2[0]->Delete(); m_Clippers2[1]->Delete(); m_Clippers2[2]->Delete(); } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D -::GetProp(mitk::BaseRenderer* renderer) +::GetVtkProp(mitk::BaseRenderer* renderer) { return m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter *pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } switch(m_Normalization) { case ODFN_MINMAX: odf = odf.MinMaxNormalize(); break; case ODFN_MAX: odf = odf.MaxNormalize(); break; case ODFN_NONE: // nothing break; case ODFN_GLOBAL_MAX: // global max not implemented yet break; default: odf = odf.MinMaxNormalize(); } switch(m_ScaleBy) { case ODFSB_NONE: m_OdfSource->SetAdditionalScale(1.0); break; case ODFSB_GFA: m_OdfSource->SetAdditionalScale(odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: m_OdfSource->SetAdditionalScale(odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } for(int i=0; iSetComponent(0,i,0.5*odf[i]*m_Scaling); //double max = -100000; //double min = 100000; //for( unsigned int i=0; i max ? odf[i] : max; // min = odf[i] < min ? odf[i] : min; //} m_OdfSource->Modified(); } template void mitk::OdfVtkMapper2D ::AdaptCameraPosition(mitk::BaseRenderer* renderer, OdfDisplayGeometry* dispGeo ) { double viewAngle = renderer->GetVtkRenderer()->GetActiveCamera()->GetViewAngle(); viewAngle = viewAngle * (ODF_MAPPER_PI/180.0); viewAngle /= 2; double dist = dispGeo->d/tan(viewAngle); mitk::Point3D mfoc; mfoc[0]=dispGeo->M3D[0]; mfoc[1]=dispGeo->M3D[1]; mfoc[2]=dispGeo->M3D[2]; mitk::Point3D mpos; mpos[0]=mfoc[0]+dist*dispGeo->normal[0]; mpos[1]=mfoc[1]+dist*dispGeo->normal[1]; mpos[2]=mfoc[2]+dist*dispGeo->normal[2]; mitk::Point3D mup; mup[0]=dispGeo->O3D[0]-dispGeo->M3D[0]; mup[1]=dispGeo->O3D[1]-dispGeo->M3D[1]; mup[2]=dispGeo->O3D[2]-dispGeo->M3D[2]; renderer->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(true); renderer->GetVtkRenderer()->GetActiveCamera()->SetParallelScale(dist/3.74); vtkCamera* camera = renderer->GetVtkRenderer()->GetActiveCamera(); if (camera) { camera->SetPosition(mpos[0],mpos[1],mpos[2]); camera->SetFocalPoint(mfoc[0], mfoc[1],mfoc[2]); camera->SetViewUp(mup[0],mup[1],mup[2]); } renderer->GetVtkRenderer()->ResetCameraClippingRange(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry* mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { - // std::cout << "MeasureDisplayedGeometry(" << renderer->GetName() << ")" << std::endl; - // vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); - Geometry2D::ConstPointer worldGeometry = + //vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); + Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); // set up the cutter orientation according to the current geometry of // the renderers plane vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; - point1[0] = M[0]; point1[1] = M[1]; - + point1[0] = M[0]; point1[1] = M[1]; point1[2] = M[2]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); - point1[0] = L[0]; point1[1] = L[1]; + point1[0] = L[0]; point1[1] = L[1]; point1[2] = L[2]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); - point1[0] = O[0]; point1[1] = O[1]; + point1[0] = O[0]; point1[1] = O[1]; point1[2] = O[2]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry* retval = new OdfDisplayGeometry(); retval->vp[0] = vp[0]; retval->vp[1] = vp[1]; retval->vp[2] = vp[2]; retval->vnormal[0] = vnormal[0]; retval->vnormal[1] = vnormal[1]; retval->vnormal[2] = vnormal[2]; retval->normal[0] = normal[0]; retval->normal[1] = normal[1]; retval->normal[2] = normal[2]; retval->d = d; retval->d1 = d1; retval->d2 = d2; retval->M3D[0] = M3D[0]; retval->M3D[1] = M3D[1]; retval->M3D[2] = M3D[2]; retval->L3D[0] = L3D[0]; retval->L3D[1] = L3D[1]; retval->L3D[2] = L3D[2]; retval->O3D[0] = O3D[0]; retval->O3D[1] = O3D[1]; retval->O3D[2] = O3D[2]; retval->vp_original[0] = vp[0]; retval->vp_original[1] = vp[1]; retval->vp_original[2] = vp[2]; retval->vnormal_original[0] = vnormal[0]; retval->vnormal_original[1] = vnormal[1]; retval->vnormal_original[2] = vnormal[2]; retval->size[0] = size[0]; retval->size[1] = size[1]; retval->origin[0] = origin[0]; retval->origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry* dispGeo) { vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkTransform* inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo->vp, dispGeo->vp ); inversetransform->TransformNormalAtPoint( dispGeo->vp, dispGeo->vnormal, dispGeo->vnormal ); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo->vnormal[0]) > fabs(dispGeo->vnormal[1]) && fabs(dispGeo->vnormal[0]) > fabs(dispGeo->vnormal[2]) ) { if(fabs(dispGeo->vp[0]/spac[0]) < 0.4) dispGeo->vp[0] = 0.4*spac[0]; if(fabs(dispGeo->vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo->vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo->vnormal[1] = 0; dispGeo->vnormal[2] = 0; } if(fabs(dispGeo->vnormal[1]) > fabs(dispGeo->vnormal[0]) && fabs(dispGeo->vnormal[1]) > fabs(dispGeo->vnormal[2]) ) { if(fabs(dispGeo->vp[1]/spac[1]) < 0.4) dispGeo->vp[1] = 0.4*spac[1]; if(fabs(dispGeo->vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo->vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo->vnormal[0] = 0; dispGeo->vnormal[2] = 0; } if(fabs(dispGeo->vnormal[2]) > fabs(dispGeo->vnormal[1]) && fabs(dispGeo->vnormal[2]) > fabs(dispGeo->vnormal[0]) ) { if(fabs(dispGeo->vp[2]/spac[2]) < 0.4) dispGeo->vp[2] = 0.4*spac[2]; if(fabs(dispGeo->vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo->vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo->vnormal[0] = 0; dispGeo->vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo->vp ); m_Planes[index]->SetNormal( dispGeo->vnormal ); vtkPoints* points = NULL; vtkPoints* tmppoints = NULL; vtkPolyData* polydata = NULL; vtkFloatArray* pointdata = NULL; vtkDelaunay2D *delaunay = NULL; vtkPolyData* cuttedPlane = NULL; - if(!( (dims[0] == 1 && dispGeo->vnormal[0] != 0) || + + // the cutter only works if we do not have a 2D-image + // or if we have a 2D-image and want to see the whole image. + // + // for side views of 2D-images, we need some special treatment + if(!( (dims[0] == 1 && dispGeo->vnormal[0] != 0) || (dims[1] == 1 && dispGeo->vnormal[1] != 0) || (dims[2] == 1 && dispGeo->vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInput( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInput( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo->vnormal[0] = dispGeo->M3D[0]-dispGeo->O3D[0]; dispGeo->vnormal[1] = dispGeo->M3D[1]-dispGeo->O3D[1]; dispGeo->vnormal[2] = dispGeo->M3D[2]-dispGeo->O3D[2]; vtkMath::Normalize(dispGeo->vnormal); dispGeo->vp[0] = dispGeo->M3D[0]; dispGeo->vp[1] = dispGeo->M3D[1]; dispGeo->vp[2] = dispGeo->M3D[2]; inversetransform->TransformPoint( dispGeo->vp, dispGeo->vp ); inversetransform->TransformNormalAtPoint( dispGeo->vp, dispGeo->vnormal, dispGeo->vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo->vnormal, dispGeo->vp ); m_ThickPlanes1[index]->SetThickness(dispGeo->d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInput( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo->vnormal[0] = dispGeo->M3D[0]-dispGeo->L3D[0]; dispGeo->vnormal[1] = dispGeo->M3D[1]-dispGeo->L3D[1]; dispGeo->vnormal[2] = dispGeo->M3D[2]-dispGeo->L3D[2]; vtkMath::Normalize(dispGeo->vnormal); dispGeo->vp[0] = dispGeo->M3D[0]; dispGeo->vp[1] = dispGeo->M3D[1]; dispGeo->vp[2] = dispGeo->M3D[2]; inversetransform->TransformPoint( dispGeo->vp, dispGeo->vp ); inversetransform->TransformNormalAtPoint( dispGeo->vp, dispGeo->vnormal, dispGeo->vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo->vnormal, dispGeo->vp ); m_ThickPlanes2[index]->SetThickness(dispGeo->d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInput( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { m_OdfsPlanes[index]->RemoveAllInputs(); vtkPolyDataNormals* normals = vtkPolyDataNormals::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkTransformPolyDataFilter* trans = vtkTransformPolyDataFilter::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkMaskedProgrammableGlyphFilter* glyphGenerator = vtkMaskedProgrammableGlyphFilter::New(); glyphGenerator->SetMaximumNumberOfPoints(m_ShowMaxNumber); glyphGenerator->SetRandomMode(1); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSource( trans->GetOutput() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } m_OdfsPlanes[index]->AddInput(glyphGenerator->GetOutput()); trans->Delete(); glyphGenerator->Delete(); normals->Delete(); m_OdfsPlanes[index]->Update(); } } m_PropAssemblies[index]->VisibilityOn(); if(m_PropAssemblies[index]->GetParts()->IsItemPresent(m_OdfsActors[index])) m_PropAssemblies[index]->RemovePart(m_OdfsActors[index]); m_OdfsMappers[index]->SetInput(m_OdfsPlanes[index]->GetOutput()); m_PropAssemblies[index]->AddPart(m_OdfsActors[index]); if(inversetransform) inversetransform->Delete(); if(points) points->Delete(); if(pointdata) pointdata->Delete(); if(tmppoints) tmppoints->Delete(); if(polydata) polydata->Delete(); if(delaunay) delaunay->Delete(); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: retval = this->IsVisible(renderer, "VisibleOdfs_T"); break; case 1: retval = this->IsVisible(renderer, "VisibleOdfs_S"); break; case 2: retval = this->IsVisible(renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { //std::cout << "MitkRenderOverlay(" << renderer->GetName() << ")" << std::endl; if ( this->IsVisibleOdfs(renderer)==false ) return; - if ( this->GetProp(renderer)->GetVisibility() ) + if ( this->GetVtkProp(renderer)->GetVisibility() ) { - this->GetProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); + this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { // std::cout << "MitkRenderOpaqueGeometry(" << renderer->GetName() << ")" << std::endl; if ( this->IsVisibleOdfs( renderer )==false ) return; - if ( this->GetProp(renderer)->GetVisibility() ) + if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos OdfDisplayGeometry* dispGeo = MeasureDisplayedGeometry( renderer); + //AdaptCameraPosition(renderer, dispGeo); - AdaptCameraPosition(renderer, dispGeo); - - if(this->GetDataNode()->IsOn("DoRefresh",NULL)) + if(/*this->GetDataNode()->IsOn("DoRefresh",NULL)*/false) { glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); renderer->GetVtkRenderer()->SetErase(false); renderer->GetVtkRenderer()->GetActiveCamera()->Render(renderer->GetVtkRenderer()); renderer->GetVtkRenderer()->SetErase(true); //GLfloat matrix[16]; //glGetFloatv(GL_MODELVIEW_MATRIX, matrix); float LightPos[4] = {0,0,0,0}; int index = GetIndex(renderer); if(index==0) { LightPos[2] = -1000; } if(index==1) { LightPos[0] = 1000; } if(index==2) { LightPos[1] = -1000; } glLightfv(GL_LIGHT0,GL_POSITION,LightPos); glLightfv(GL_LIGHT1,GL_POSITION,LightPos); glLightfv(GL_LIGHT2,GL_POSITION,LightPos); glLightfv(GL_LIGHT3,GL_POSITION,LightPos); glLightfv(GL_LIGHT4,GL_POSITION,LightPos); glLightfv(GL_LIGHT5,GL_POSITION,LightPos); glLightfv(GL_LIGHT6,GL_POSITION,LightPos); glLightfv(GL_LIGHT7,GL_POSITION,LightPos); } - this->GetProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); + this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - if(this->GetDataNode()->IsOn("DoRefresh",NULL)) + if(/*this->GetDataNode()->IsOn("DoRefresh",NULL)*/false) { glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); } } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { //std::cout << "MitkRenderTranslucentGeometry(" << renderer->GetName() << ")" << std::endl; if ( this->IsVisibleOdfs(renderer)==false ) return; - if ( this->GetProp(renderer)->GetVisibility() ) - this->GetProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); + if ( this->GetVtkProp(renderer)->GetVisibility() ) + this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::GenerateData() { mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) { m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); } std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) { m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); } if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template void mitk::OdfVtkMapper2D ::AdaptOdfScalingToImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } m_OdfSource->SetScale(min); } template void mitk::OdfVtkMapper2D ::SetRendererLightSources( mitk::BaseRenderer *renderer ) { // Light Sources vtkCollectionSimpleIterator sit; vtkLight* light; for(renderer->GetVtkRenderer()->GetLights()->InitTraversal(sit); (light = renderer->GetVtkRenderer()->GetLights()->GetNextLight(sit)); ) { renderer->GetVtkRenderer()->RemoveLight(light); } light = vtkLight::New(); light->SetFocalPoint(0,0,0); light->SetLightTypeToSceneLight(); light->SwitchOn(); light->SetIntensity(1.0); light->PositionalOff(); itk::Point p; int index = GetIndex(renderer); if(index==0) { p[0] = 0; p[1] = 0; p[2] = 10000; } if(index==1) { p[0] = 0; p[1] = 10000; p[2] = 0; } if(index==2) { p[0] = 10000; p[1] = 0; p[2] = 0; } mitk::Point3D p2; this->GetInput()->GetGeometry()->IndexToWorld(p,p2); light->SetPosition(p2[0],p2[1],p2[2]); renderer->GetVtkRenderer()->AddLight(light); } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast ( this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) { m_Normalization = nmp->GetNormalization(); } OdfScaleByProperty* sbp = dynamic_cast ( this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) { m_ScaleBy = sbp->GetScaleBy(); } this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); vtkFloatingPointType vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.Get_vnl_vector(), vnormal ); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkTransform* inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double* n = inversetransform->TransformNormal(vnormal); int nonZeros = 0; for (int j=0; j<3; j++) { if (fabs(n[j])>1e-7){ nonZeros++; } } if(nonZeros>1) return true; return false; } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { if(!m_VtkImage) { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } int index = GetIndex(renderer); if(IsVisibleOdfs(renderer)==false) { m_OdfsActors[0]->VisibilityOff(); m_OdfsActors[1]->VisibilityOff(); m_OdfsActors[2]->VisibilityOff(); return; } else { m_OdfsActors[0]->VisibilityOn(); m_OdfsActors[1]->VisibilityOn(); m_OdfsActors[2]->VisibilityOn(); OdfDisplayGeometry* dispGeo = MeasureDisplayedGeometry( renderer); if(!m_LastDisplayGeometry || !dispGeo->Equals(m_LastDisplayGeometry)) { AdaptOdfScalingToImageSpacing(index); SetRendererLightSources(renderer); ApplyPropertySettings(); - AdaptCameraPosition(renderer, dispGeo); + //AdaptCameraPosition(renderer, dispGeo); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } } // Get the TimeSlicedGeometry of the input object mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 )) { m_PropAssemblies[0]->VisibilityOff(); m_PropAssemblies[1]->VisibilityOff(); m_PropAssemblies[2]->VisibilityOff(); return; } if( inputTimeGeometry->IsValidTime( this->GetTimestep() ) == false ) { m_PropAssemblies[0]->VisibilityOff(); m_PropAssemblies[1]->VisibilityOff(); m_PropAssemblies[2]->VisibilityOff(); return; } } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); //node->SetProperty( "opacity", mitk::FloatProperty::New(1.0f) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/IGT/IGTFilters/mitkCameraVisualization.cpp b/Modules/IGT/IGTFilters/mitkCameraVisualization.cpp index 02d51a5890..22caac4b00 100644 --- a/Modules/IGT/IGTFilters/mitkCameraVisualization.cpp +++ b/Modules/IGT/IGTFilters/mitkCameraVisualization.cpp @@ -1,142 +1,141 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkCameraVisualization.h" #include "vtkCamera.h" #include "mitkPropertyList.h" #include "mitkProperties.h" mitk::CameraVisualization::CameraVisualization(): NavigationDataToNavigationDataFilter(), m_Renderer(NULL), m_FocalLength(10.0) { // initialize members m_DirectionOfProjectionInToolCoordinates[0] = 0; m_DirectionOfProjectionInToolCoordinates[1] = 0; m_DirectionOfProjectionInToolCoordinates[2] = -1; m_ViewUpInToolCoordinates[0] = 1; m_ViewUpInToolCoordinates[1] = 0; m_ViewUpInToolCoordinates[2] = 0; - m_DirectionOfProjection.Fill(0); } mitk::CameraVisualization::~CameraVisualization() { } void mitk::CameraVisualization::GenerateData() { // check if renderer was set if (m_Renderer.IsNull()) itkExceptionMacro(<< "Renderer was not properly set"); /* update outputs with tracking data from tools */ unsigned int numberOfInputs = this->GetNumberOfInputs(); for (unsigned int i = 0; i < numberOfInputs ; ++i) { mitk::NavigationData* output = this->GetOutput(i); assert(output); const mitk::NavigationData* input = this->GetInput(i); assert(input); if (input->IsDataValid() == false) { continue; } output->Graft(input); // First, copy all information from input to output } const NavigationData* navigationData = this->GetInput(); // get position from NavigationData to move the camera to this position - m_CameraPosition = navigationData->GetPosition(); + Point3D cameraPosition = navigationData->GetPosition(); //calculate the transform from the quaternions static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); mitk::NavigationData::OrientationType orientation = navigationData->GetOrientation(); // convert mitk::Scalartype quaternion to double quaternion because of itk bug vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); quatTransform->SetIdentity(); quatTransform->SetRotation(doubleQuaternion); quatTransform->Modified(); /* because of an itk bug, the transform can not be calculated with float datatype. To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ static AffineTransform3D::MatrixType m; mitk::TransferMatrix(quatTransform->GetMatrix(), m); - m_DirectionOfProjection = m*m_DirectionOfProjectionInToolCoordinates; - m_DirectionOfProjection.Normalize(); - Point3D focalPoint = m_CameraPosition + m_FocalLength*m_DirectionOfProjection; + Vector3D directionOfProjection = m*m_DirectionOfProjectionInToolCoordinates; + directionOfProjection.Normalize(); + Point3D focalPoint = cameraPosition + m_FocalLength*directionOfProjection; // compute current view up vector Vector3D viewUp = m*m_ViewUpInToolCoordinates; - m_Renderer->GetVtkRenderer()->GetActiveCamera()->SetPosition(m_CameraPosition[0],m_CameraPosition[1],m_CameraPosition[2]); + m_Renderer->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition[0],cameraPosition[1],cameraPosition[2]); m_Renderer->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(focalPoint[0],focalPoint[1],focalPoint[2]); m_Renderer->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp[0],viewUp[1],viewUp[2]); m_Renderer->GetVtkRenderer()->ResetCameraClippingRange(); m_Renderer->RequestUpdate(); } void mitk::CameraVisualization::SetRenderer(mitk::BaseRenderer* renderer) { m_Renderer = renderer; } const mitk::BaseRenderer* mitk::CameraVisualization::GetRenderer() { return m_Renderer; } void mitk::CameraVisualization::SetParameters( const mitk::PropertyList* p ) { if (p == NULL) return; mitk::Vector3D doP; if (p->GetPropertyValue("CameraVisualization_DirectionOfProjectionInToolCoordinates", doP) == true) // search for DirectionOfProjectionInToolCoordinates parameter this->SetDirectionOfProjectionInToolCoordinates(doP); // apply if found; mitk::Vector3D vUp; if (p->GetPropertyValue("CameraVisualization_ViewUpInToolCoordinates", vUp) == true) // search for ViewUpInToolCoordinates parameter this->SetViewUpInToolCoordinates(vUp); // apply if found; float fL; if (p->GetPropertyValue("CameraVisualization_FocalLength", fL) == true) // search for FocalLength parameter this->SetFocalLength(fL); // apply if found; float vA; if (p->GetPropertyValue("CameraVisualization_ViewAngle", vA) == true) // search for ViewAngle parameter this->SetFocalLength(vA); // apply if found; } mitk::PropertyList::ConstPointer mitk::CameraVisualization::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); p->SetProperty("CameraVisualization_DirectionOfProjectionInToolCoordinates", mitk::Vector3DProperty::New(this->GetDirectionOfProjectionInToolCoordinates())); // store DirectionOfProjectionInToolCoordinates parameter p->SetProperty("CameraVisualization_ViewUpInToolCoordinates", mitk::Vector3DProperty::New(this->GetViewUpInToolCoordinates())); // store ViewUpInToolCoordinates parameter p->SetProperty("CameraVisualization_FocalLength", mitk::Vector3DProperty::New(this->GetFocalLength())); // store FocalLength parameter return mitk::PropertyList::ConstPointer(p); } diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp index e2999cf028..316a226e5d 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp @@ -1,504 +1,504 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/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 notices for more information. =========================================================================*/ #include "mitkExtractDirectedPlaneImageFilter.h" #include "mitkAbstractTransformGeometry.h" -#include "mitkImageMapperGL2D.h" +//#include "mitkImageMapperGL2D.h" #include #include #include #include #include #include "pic2vtk.h" mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter() : m_WorldGeometry(NULL) { m_Reslicer = vtkImageReslice::New(); m_TargetTimestep = 0; m_InPlaneResampleExtentByGeometry = false; } mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter() { m_WorldGeometry = NULL; m_Reslicer->Delete(); } void mitk::ExtractDirectedPlaneImageFilter::GenerateData() { // A world geometry must be set... if ( m_WorldGeometry == NULL ) { itkWarningMacro(<<"No world geometry has been set. Returning."); return; } Image *input = const_cast< ImageToImageFilter::InputImageType* >( this->GetInput() ); input->Update(); if ( input == NULL ) { itkWarningMacro(<<"No input set."); return; } const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); if ( ( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) { itkWarningMacro(<<"Error reading input image geometry."); return; } // Get the target timestep; if none is set, use the lowest given. unsigned int timestep = 0; if ( ! m_TargetTimestep ) { ScalarType time = m_WorldGeometry->GetTimeBounds()[0]; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) { timestep = inputTimeGeometry->MSToTimeStep( time ); } } else timestep = m_TargetTimestep; if ( inputTimeGeometry->IsValidTime( timestep ) == false ) { itkWarningMacro(<<"This is not a valid timestep: "<IsVolumeSet( timestep ) ) { itkWarningMacro(<<"No volume data existent at given timestep "<GetLargestPossibleRegion(); requestedRegion.SetIndex( 3, timestep ); requestedRegion.SetSize( 3, 1 ); requestedRegion.SetSize( 4, 1 ); input->SetRequestedRegion( &requestedRegion ); input->Update(); vtkImageData* inputData = input->GetVtkImageData( timestep ); if ( inputData == NULL ) { itkWarningMacro(<<"Could not extract vtk image data for given timestep"<GetSpacing( spacing ); // how big the area is in physical coordinates: widthInMM x heightInMM pixels mitk::ScalarType widthInMM, heightInMM; // where we want to sample Point3D origin; Vector3D right, bottom, normal; Vector3D rightInIndex, bottomInIndex; assert( input->GetTimeSlicedGeometry() == inputTimeGeometry ); // take transform of input image into account Geometry3D* inputGeometry = inputTimeGeometry->GetGeometry3D( timestep ); if ( inputGeometry == NULL ) { itkWarningMacro(<<"There is no Geometry3D at given timestep "<( m_WorldGeometry ) != NULL ) { const PlaneGeometry *planeGeometry = static_cast< const PlaneGeometry * >( m_WorldGeometry ); origin = planeGeometry->GetOrigin(); right = planeGeometry->GetAxisVector( 0 ); bottom = planeGeometry->GetAxisVector( 1 ); normal = planeGeometry->GetNormal(); if ( m_InPlaneResampleExtentByGeometry ) { // Resampling grid corresponds to the current world geometry. This // means that the spacing of the output 2D image depends on the // currently selected world geometry, and *not* on the image itself. extent[0] = m_WorldGeometry->GetExtent( 0 ); extent[1] = m_WorldGeometry->GetExtent( 1 ); } else { // Resampling grid corresponds to the input geometry. This means that // the spacing of the output 2D image is directly derived from the // associated input image, regardless of the currently selected world // geometry. inputGeometry->WorldToIndex( right, rightInIndex ); inputGeometry->WorldToIndex( bottom, bottomInIndex ); extent[0] = rightInIndex.GetNorm(); extent[1] = bottomInIndex.GetNorm(); } // Get the extent of the current world geometry and calculate resampling // spacing therefrom. widthInMM = m_WorldGeometry->GetExtentInMM( 0 ); heightInMM = m_WorldGeometry->GetExtentInMM( 1 ); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; right.Normalize(); bottom.Normalize(); normal.Normalize(); //origin += right * ( mmPerPixel[0] * 0.5 ); //origin += bottom * ( mmPerPixel[1] * 0.5 ); //widthInMM -= mmPerPixel[0]; //heightInMM -= mmPerPixel[1]; // Use inverse transform of the input geometry for reslicing the 3D image m_Reslicer->SetResliceTransform( inputGeometry->GetVtkTransform()->GetLinearInverse() ); // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -32768 ); // Check if a reference geometry does exist (as would usually be the case for // PlaneGeometry). // Note: this is currently not strictly required, but could facilitate // correct plane clipping. if ( m_WorldGeometry->GetReferenceGeometry() ) { // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. boundsInitialized = this->CalculateClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, bounds ); } } // Do we have an AbstractTransformGeometry? else if ( dynamic_cast< const AbstractTransformGeometry * >( m_WorldGeometry ) ) { const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); extent[0] = abstractGeometry->GetParametricExtent(0); extent[1] = abstractGeometry->GetParametricExtent(1); widthInMM = abstractGeometry->GetParametricExtentInMM(0); heightInMM = abstractGeometry->GetParametricExtentInMM(1); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; origin = abstractGeometry->GetPlane()->GetOrigin(); right = abstractGeometry->GetPlane()->GetAxisVector(0); right.Normalize(); bottom = abstractGeometry->GetPlane()->GetAxisVector(1); bottom.Normalize(); normal = abstractGeometry->GetPlane()->GetNormal(); normal.Normalize(); // Use a combination of the InputGeometry *and* the possible non-rigid // AbstractTransformGeometry for reslicing the 3D Image vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( inputGeometry->GetVtkTransform()->GetLinearInverse() ); composedResliceTransform->Concatenate( abstractGeometry->GetVtkAbstractTransform() ); m_Reslicer->SetResliceTransform( composedResliceTransform ); // Set background level to BLACK instead of translucent, to avoid // boundary artifacts (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -1023 ); composedResliceTransform->Delete(); } else { itkWarningMacro(<<"World Geometry has to be a PlaneGeometry or an AbstractTransformGeometry."); return; } // Make sure that the image to be resliced has a certain minimum size. if ( (extent[0] <= 2) && (extent[1] <= 2) ) { itkWarningMacro(<<"Image is too small to be resliced..."); return; } vtkImageChangeInformation * unitSpacingImageFilter = vtkImageChangeInformation::New() ; unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); unitSpacingImageFilter->SetInput( inputData ); m_Reslicer->SetInput( unitSpacingImageFilter->GetOutput() ); unitSpacingImageFilter->Delete(); //m_Reslicer->SetInput( inputData ); m_Reslicer->SetOutputDimensionality( 2 ); m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); Vector2D pixelsPerMM; pixelsPerMM[0] = 1.0 / mmPerPixel[0]; pixelsPerMM[1] = 1.0 / mmPerPixel[1]; //calulate the originArray and the orientations for the reslice-filter double originArray[3]; itk2vtk( origin, originArray ); m_Reslicer->SetResliceAxesOrigin( originArray ); double cosines[9]; // direction of the X-axis of the sampled result vnl2vtk( right.Get_vnl_vector(), cosines ); // direction of the Y-axis of the sampled result vnl2vtk( bottom.Get_vnl_vector(), cosines + 3 ); // normal of the plane vnl2vtk( normal.Get_vnl_vector(), cosines + 6 ); m_Reslicer->SetResliceAxesDirectionCosines( cosines ); // Determine output extent for reslicing ScalarType size[2]; size[0] = (bounds[1] - bounds[0]) / mmPerPixel[0]; size[1] = (bounds[3] - bounds[2]) / mmPerPixel[1]; int xMin, xMax, yMin, yMax; if ( boundsInitialized ) { xMin = static_cast< int >( bounds[0] / mmPerPixel[0] );//+ 0.5 ); xMax = static_cast< int >( bounds[1] / mmPerPixel[0] );//+ 0.5 ); yMin = static_cast< int >( bounds[2] / mmPerPixel[1] );//+ 0.5); yMax = static_cast< int >( bounds[3] / mmPerPixel[1] );//+ 0.5 ); } else { // If no reference geometry is available, we also don't know about the // maximum plane size; so the overlap is just ignored xMin = yMin = 0; xMax = static_cast< int >( extent[0] - pixelsPerMM[0] );//+ 0.5 ); yMax = static_cast< int >( extent[1] - pixelsPerMM[1] );//+ 0.5 ); } m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], 1.0 ); // xMax and yMax are meant exclusive until now, whereas // SetOutputExtent wants an inclusive bound. Thus, we need // to subtract 1. m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 1 ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. m_Reslicer->Modified(); m_Reslicer->ReleaseDataFlagOn(); m_Reslicer->Update(); // 1. Check the result vtkImageData* reslicedImage = m_Reslicer->GetOutput(); mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage ); if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) { itkWarningMacro(<<"Reslicer returned empty image"); return; } unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize( pic ); resultImage->SetSpacing( spacingVector ); resultImage->SetPicVolume( pic ); mitkIpPicFree(pic); /*unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize(m_Reslicer->GetOutput()); resultImage->Initialize(inputImage->GetPixelType(), 2, dimensions); resultImage->SetSpacing(spacingVector); resultImage->SetSlice(m_Reslicer->GetOutput());*/ } void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); } bool mitk::ExtractDirectedPlaneImageFilter ::CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) { // Clip the plane with the bounding geometry. To do so, the corner points // of the bounding box are transformed by the inverse transformation // matrix, and the transformed bounding box edges derived therefrom are // clipped with the plane z=0. The resulting min/max values are taken as // bounds for the image reslicer. const BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); BoundingBox::PointType bbMin = boundingBox->GetMinimum(); BoundingBox::PointType bbMax = boundingBox->GetMaximum(); BoundingBox::PointType bbCenter = boundingBox->GetCenter(); vtkPoints *points = vtkPoints::New(); if(boundingGeometry->GetImageGeometry()) { points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); } else { points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); } vtkPoints *newPoints = vtkPoints::New(); vtkTransform *transform = vtkTransform::New(); transform->Identity(); transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); transform->Concatenate( boundingGeometry->GetVtkTransform() ); transform->TransformPoints( points, newPoints ); transform->Delete(); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; this->LineIntersectZero( newPoints, 0, 1, bounds ); this->LineIntersectZero( newPoints, 1, 2, bounds ); this->LineIntersectZero( newPoints, 2, 3, bounds ); this->LineIntersectZero( newPoints, 3, 0, bounds ); this->LineIntersectZero( newPoints, 0, 4, bounds ); this->LineIntersectZero( newPoints, 1, 5, bounds ); this->LineIntersectZero( newPoints, 2, 6, bounds ); this->LineIntersectZero( newPoints, 3, 7, bounds ); this->LineIntersectZero( newPoints, 4, 5, bounds ); this->LineIntersectZero( newPoints, 5, 6, bounds ); this->LineIntersectZero( newPoints, 6, 7, bounds ); this->LineIntersectZero( newPoints, 7, 4, bounds ); // clean up vtk data points->Delete(); newPoints->Delete(); if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const float *planeSpacing = planeGeometry->GetFloatSpacing(); bounds[0] *= planeSpacing[0]; bounds[1] *= planeSpacing[0]; bounds[2] *= planeSpacing[1]; bounds[3] *= planeSpacing[1]; bounds[4] *= planeSpacing[2]; bounds[5] *= planeSpacing[2]; return true; } } bool mitk::ExtractDirectedPlaneImageFilter ::LineIntersectZero( vtkPoints *points, int p1, int p2, vtkFloatingPointType *bounds ) { vtkFloatingPointType point1[3]; vtkFloatingPointType point2[3]; points->GetPoint( p1, point1 ); points->GetPoint( p2, point2 ); if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) { double x, y; x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); if ( x < bounds[0] ) { bounds[0] = x; } if ( x > bounds[1] ) { bounds[1] = x; } if ( y < bounds[2] ) { bounds[2] = y; } if ( y > bounds[3] ) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; }