diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp index d656a6889a..5d42144101 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp @@ -1,810 +1,713 @@ /*========================================================================= 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 "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_DisplayNormals(false), - m_ColorTwoSides(false), - m_InvertNormals(true), - m_NormalsActorAdded(false), - m_DataStorage(NULL) -{ - m_EdgeTuber = vtkTubeFilter::New(); - m_EdgeMapper = vtkPolyDataMapper::New(); - - // Disable OGL Displaylist for the "Edge". Workaround for Bug #1787 - // m_EdgeMapper->ImmediateModeRenderingOn(); - - 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_BackgroundMapper->ImmediateModeRenderingOn(); - 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_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) + Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D() { - if ( it->second.LookupTableSource != NULL ) + 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) { - it->second.LookupTableSource->Delete(); - it->second.LookupTableSource = NULL; + if ( it->second.LookupTableSource != NULL ) + { + it->second.LookupTableSource->Delete(); + it->second.LookupTableSource = NULL; + } } + m_DataStorage = NULL; } - m_DataStorage = NULL; -} - -vtkProp* Geometry2DDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) -{ - if ( (this->GetDataNode() != NULL ) - && (m_ImageAssembly != NULL) ) + vtkProp* Geometry2DDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { - // 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() ); + 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; } - 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::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) + void Geometry2DDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage* storage) { - if( m_DataStorage != storage ) + if(storage != NULL && m_DataStorage != storage ) { m_DataStorage = storage; this->Modified(); } } -} - -// -// METHOD COMMENTED OUT SINCE IT IS CURRENTLY UNUSED -// -//void -//Geometry2DDataVtkMapper3D::BuildPaddedLookupTable( -// vtkLookupTable *inputLookupTable, vtkLookupTable *outputLookupTable, -// vtkFloatingPointType min, vtkFloatingPointType max ) -//{ -// // Copy the table values from the input lookup table -// vtkUnsignedCharArray *inputTable = vtkUnsignedCharArray::New(); -// inputTable->DeepCopy( inputLookupTable->GetTable() ); -// -// vtkUnsignedCharArray *outputTable = outputLookupTable->GetTable(); -// -// // Calculate the size of one lookup table "bin" -// vtkFloatingPointType binSize = (max - min) / 256.0; -// -// // Calculate the extended table size, assuming the range [-32767, max], -// // increased by 1. -// int tableSize = (int) ((max + 32767) / binSize) + 1; -// outputLookupTable->SetNumberOfTableValues( tableSize ); -// -// unsigned char *inputPtr = inputTable->WritePointer( 0, 0 ); -// unsigned char *outputPtr = outputTable->WritePointer( 0, 0 ); -// -// // Initialize the first (translucent) bin. -// *outputPtr++ = 0; *outputPtr++ = 0; *outputPtr++ = 0; *outputPtr++ = 0; -// -// int i; -// for ( i = 1; i < tableSize; ++i ) -// { -// *outputPtr++ = *inputPtr++; -// *outputPtr++ = *inputPtr++; -// *outputPtr++ = *inputPtr++; -// *outputPtr++ = *inputPtr++; -// -// // While filling the padded part of the table, use the default value -// // (the first value of the input table) -// if ( i < (tableSize - 256) ) -// { -// inputPtr -= 4; -// } -// } -// -// // Apply the new table range; the lower boundary is decreased by binSize -// // since we have one additional translucent bin. -// outputLookupTable->SetTableRange( -32767.0 - binSize, max ); -// -// inputTable->Delete(); -//} - - -int - Geometry2DDataVtkMapper3D::FindPowerOfTwo( int i ) -{ - int size; - for ( --i, size = 1; i > 0; size *= 2 ) + void Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback( + itk::Object *caller, const itk::EventObject& /*event*/ ) { - i /= 2; - } - return size; -} - -void - Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback( - itk::Object *caller, const itk::EventObject& /*event*/ ) -{ - ImageMapperGL2D *imageMapper = dynamic_cast< ImageMapperGL2D * >( 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 ) + ImageMapperGL2D *imageMapper = dynamic_cast< ImageMapperGL2D * >( caller ); + if ( (imageMapper != NULL) ) { - m_LookupTableProperties[imageMapper].LookupTableSource->Delete(); - m_LookupTableProperties.erase( imageMapper ); + 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::GenerateData(BaseRenderer* renderer) + { + SetVtkMapperImmediateModeRendering(m_EdgeMapper); + SetVtkMapperImmediateModeRendering(m_BackgroundMapper); -void Geometry2DDataVtkMapper3D::GenerateData(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(); - // 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; + } - 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(); + m_ImageAssembly->VisibilityOn(); + m_EdgeActor->VisibilityOn(); - Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput()); + 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() ) - ) + if (input.IsNotNull() && (input->GetGeometry2D() != NULL)) { - //m_SurfaceCreator = Geometry2DDataToSurfaceFilter::New(); - m_SurfaceCreator->PlaceByGeometryOn(); - surfacecreatorprop = SmartPointerProperty::New( m_SurfaceCreator ); - GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop); - } + SmartPointerProperty::Pointer surfacecreatorprop; + surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer)); - 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); - } + 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); + } - double tubeRadius = 1.0; // Radius of tubular edge surrounding plane + m_SurfaceCreator->SetInput(input); - // Clip the Geometry2D with the reference geometry bounds (if available) - if ( input->GetGeometry2D()->HasReferenceGeometry() ) - { - Geometry3D *referenceGeometry = - input->GetGeometry2D()->GetReferenceGeometry(); + int res; + if (GetDataNode()->GetIntProperty("xresolution", res, renderer)) + { + m_SurfaceCreator->SetXResolution(res); + } + if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) + { + m_SurfaceCreator->SetYResolution(res); + } - BoundingBox::PointType boundingBoxMin, boundingBoxMax; - boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); - boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); + double tubeRadius = 1.0; // Radius of tubular edge surrounding plane - if ( referenceGeometry->GetImageGeometry() ) + // Clip the Geometry2D with the reference geometry bounds (if available) + if ( input->GetGeometry2D()->HasReferenceGeometry() ) { - for ( unsigned int i = 0; i < 3; ++i ) + Geometry3D *referenceGeometry = + input->GetGeometry2D()->GetReferenceGeometry(); + + BoundingBox::PointType boundingBoxMin, boundingBoxMax; + boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); + boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); + + if ( referenceGeometry->GetImageGeometry() ) { - boundingBoxMin[i] -= 0.5; - boundingBoxMax[i] -= 0.5; + 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_SurfaceCreatorPointsContainer->CreateElementAt( 0 ) = boundingBoxMin; + m_SurfaceCreatorPointsContainer->CreateElementAt( 1 ) = boundingBoxMax; - m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); + m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); - m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox ); + m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox ); + + tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; + } - tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; - } - else - { // If no reference geometry is available, clip with the current global // bounds - if (m_DataStorage.IsNotNull()) + 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(); + // 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(); - node->GetBoolProperty("draw normals 3D", m_DisplayNormals, renderer); - node->GetBoolProperty("color two sides", m_ColorTwoSides, renderer); - node->GetBoolProperty("invert normals", m_InvertNormals, renderer); - - if ( m_DisplayNormals || m_ColorTwoSides ) - { - 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" ); + // Check if there's something to display, otherwise return + if ( (surface->GetVtkPolyData() == 0 ) + || (surface->GetVtkPolyData()->GetNumberOfCells() == 0) ) + { + m_ImageAssembly->VisibilityOff(); + return; + } - if ( m_DisplayNormals ) + // 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 ) { - m_NormalsTransformer->SetInput( surface->GetVtkPolyData() ); - m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) ); + //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" ); - m_FrontHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); - m_FrontHedgeHog->SetVectorModeToUseNormal(); - m_FrontHedgeHog->SetScaleFactor( m_InvertNormals ? 1.0 : -1.0 ); + if ( displayNormals ) + { + m_NormalsTransformer->SetInput( surface->GetVtkPolyData() ); + m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) ); - m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); + m_FrontHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); + m_FrontHedgeHog->SetVectorModeToUseNormal(); + m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 ); - m_BackHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); - m_BackHedgeHog->SetVectorModeToUseNormal(); - m_BackHedgeHog->SetScaleFactor( m_InvertNormals ? -1.0 : 1.0 ); + m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); - m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); + m_BackHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); + m_BackHedgeHog->SetVectorModeToUseNormal(); + m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 ); - if ( !m_NormalsActorAdded ) - { - m_Prop3DAssembly->AddPart( m_FrontNormalsActor ); - m_Prop3DAssembly->AddPart( m_BackNormalsActor ); - m_NormalsActorAdded = true; - } - } + m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); - if ( m_ColorTwoSides ) - { - if ( !m_InvertNormals ) - { - m_BackgroundActor->GetBackfaceProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); - m_BackgroundActor->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; + } } - else + //if we don't want to display normals AND there is an actor added remove the actor + else if ( m_NormalsActorAdded ) { - m_BackgroundActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); - m_BackgroundActor->GetBackfaceProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); + m_Prop3DAssembly->RemovePart( m_FrontNormalsActor ); + m_Prop3DAssembly->RemovePart( m_BackNormalsActor ); + m_NormalsActorAdded = false; } - } - } - else if ( !m_DisplayNormals ) - { - 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; + // 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(); - p->AddPredicate(mitk::NodePredicateDataType::New("Image")); - p->AddPredicate(mitk::NodePredicateDataType::New("DiffusionImage")); - p->AddPredicate(mitk::NodePredicateDataType::New("TensorImage")); - p->AddPredicate(mitk::NodePredicateDataType::New("QBallImage")); - mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(p); - 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 ); + // 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) + { - // 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()) ); + DataNode *node = it->Value(); + if (node != NULL) + this->ProcessNode(node, renderer, surface, layerSortedActors); + } - // Determine maximum extent - vtkFloatingPointType* surfaceBounds = surfacePolyData->GetBounds(); - vtkFloatingPointType extent = surfaceBounds[1] - surfaceBounds[0]; - vtkFloatingPointType extentY = surfaceBounds[3] - surfaceBounds[2]; - vtkFloatingPointType extentZ = surfaceBounds[5] - surfaceBounds[4]; + // 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 ); + } - if ( extent < extentY ) - extent = extentY; - if ( extent < extentZ ) - extent = extentZ; + // 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 ); - // 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 ); + } - // 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()) ); } - 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() ); } - 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 ) + void Geometry2DDataVtkMapper3D::ProcessNode( DataNode * node, BaseRenderer* renderer, + Surface * surface, LayerSortedActorList &layerSortedActors ) { - ImageMapperGL2D *imageMapper = - dynamic_cast< ImageMapperGL2D * >( node->GetMapper(1) ); - - if(!imageMapper) + if ( node != NULL ) { - if(node->GetMapper(1)) - { + //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 + + //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")) + 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) ); } } - } - if ( (node->IsVisible(renderer)) && imageMapper ) - { - WeakPointerProperty::Pointer rendererProp = - dynamic_cast< WeakPointerProperty * >(GetDataNode()->GetPropertyList()->GetProperty("renderer")); - - if ( rendererProp.IsNotNull() ) + if ( (node->IsVisible(renderer)) && imageMapper ) { - BaseRenderer::Pointer planeRenderer = dynamic_cast< BaseRenderer * >(rendererProp->GetWeakPointer().GetPointer()); - if ( planeRenderer.IsNotNull() ) + WeakPointerProperty::Pointer rendererProp = + dynamic_cast< WeakPointerProperty * >(GetDataNode()->GetPropertyList()->GetProperty("renderer")); + + if ( rendererProp.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(); - dataSetMapper->ImmediateModeRenderingOn(); - - lookupTable = vtkLookupTable::New(); - lookupTable->DeepCopy( m_DefaultLookupTable ); - lookupTable->SetRange( -1024.0, 4095.0 ); - - texture = vtkTexture::New(); - texture->InterpolateOn(); - 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 + BaseRenderer::Pointer planeRenderer = dynamic_cast< BaseRenderer * >(rendererProp->GetWeakPointer().GetPointer()); + + if ( planeRenderer.IsNotNull() ) { - // Else, retrieve the actor and associated objects from the - // previous pass. - imageActor = m_ImageActors[imageMapper].m_Actor; - dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper(); - texture = imageActor->GetTexture(); + // 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(); - //BUG (#1551) added dynamic cast for VTK5.2 support + //BUG (#1551) added dynamic cast for VTK5.2 support #if ( ( VTK_MAJOR_VERSION >= 5 ) && ( VTK_MINOR_VERSION>=2) ) - lookupTable = dynamic_cast(texture->GetLookupTable()); + lookupTable = dynamic_cast(texture->GetLookupTable()); #else - lookupTable = texture->GetLookupTable(); + lookupTable = texture->GetLookupTable(); #endif - } + } - // Set poly data new each time its object changes (e.g. when - // switching between planar and curved geometries) - if ( dataSetMapper != NULL ) - { - if ( dataSetMapper->GetInput() != surface->GetVtkPolyData() ) + // 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(); + 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 ); + // 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(); - imageMapper->GenerateAllData(); + // ensure the right openGL context, as 3D widgets may render and take their plane texture from 2D image mappers + renderer->GetRenderWindow()->MakeCurrent(); - // 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 ); - // Retrieve and update image to be mapped - const ImageMapperGL2D::RendererInfo *rit = - imageMapper->GetRendererInfo( planeRenderer ); - if(rit->m_Image != NULL) - { - rit->m_Image->Update(); - texture->SetInput( rit->m_Image ); - // check for level-window-prop and use it if it exists - ScalarType windowMin = 0.0; - ScalarType windowMax = 255.0; - LevelWindow levelWindow; - - bool binary = false; - node->GetBoolProperty( "binary", binary, renderer ); - - // VTK (mis-)interprets unsigned char (binary) images as color images; - // So, we must manually turn on their mapping through a (gray scale) lookup table; - if( binary ) - texture->MapColorScalarsThroughLookupTableOn(); - else - texture->MapColorScalarsThroughLookupTableOff(); + //default level window + ScalarType windowMin = 0.0; + ScalarType windowMax = 255.0; + LevelWindow levelWindow; - if( binary ) - { - windowMin = 0; - windowMax = 1; - } - else if( node->GetLevelWindow( levelWindow, planeRenderer, "levelWindow" ) - || node->GetLevelWindow( levelWindow, planeRenderer ) ) - { - windowMin = levelWindow.GetLowerWindowBound(); - windowMax = levelWindow.GetUpperWindowBound(); - } + bool binary = false; + node->GetBoolProperty( "binary", binary, renderer ); - vtkLookupTable *lookupTableSource; - // check for "use color" - bool useColor; - if ( !node->GetBoolProperty( "use color", useColor, planeRenderer ) ) - useColor = false; - if ( binary ) - useColor = true; - - // check for LookupTable - LookupTableProperty::Pointer lookupTableProp; - lookupTableProp = dynamic_cast< LookupTableProperty * >(node->GetPropertyList()->GetProperty( "LookupTable" )); - - // If there is a lookup table supplied, use it; otherwise, - // use the default grayscale table - if ( lookupTableProp.IsNotNull() && !useColor ) - { - lookupTableSource = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); - } - else - { - lookupTableSource = m_DefaultLookupTable; - } + // check for "use color" + bool useColor = false; + node->GetBoolProperty( "use color", useColor, planeRenderer ); - LookupTableProperties &lutProperties = - m_LookupTableProperties[imageMapper]; + // 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 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 ) + //if we have a binary image, the range is just 0 to 1 + if( binary ) { - lutProperties.LookupTableSource->Delete(); + windowMin = 0; + windowMax = 1; + useColor = true; } - lutProperties.LookupTableSource = lookupTableSource; - lutProperties.LookupTableSource->Register( NULL ); - lutProperties.windowMin = windowMin; - lutProperties.windowMax = windowMax; - lookupTable->DeepCopy( lookupTableSource ); - lookupTable->SetRange( windowMin, windowMax ); - } + // 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) - float rgb[3] = { 1.0, 1.0, 1.0 }; - node->GetColor( rgb, renderer ); - imageActor->GetProperty()->SetColor( rgb[0], rgb[1], rgb[2] ); - //m_BackgroundActor->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 ) ); + // 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) -{ -} + 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() -{ - if(m_Sender != NULL) + Geometry2DDataVtkMapper3D::ActorInfo::ActorInfo() : m_Actor(NULL), m_Sender(NULL), m_ObserverID(0) { - m_Sender->RemoveObserver(m_ObserverID); } - if(m_Actor != NULL) + + Geometry2DDataVtkMapper3D::ActorInfo::~ActorInfo() { - m_Actor->Delete(); + 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 19a0efb044..a19efee794 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h @@ -1,256 +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 "mitkCommon.h" #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 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. + * 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 GenerateData(BaseRenderer* renderer); - typedef std::multimap< int, vtkActor * > LayerSortedActorList; - void ProcessNode( DataNode * node, BaseRenderer* renderer, Surface * surface, LayerSortedActorList &layerSortedActors ); - /* - * \brief Construct an extended lookup table from the given one. - * - * In order to overlay differently sized images over each other, it is - * necessary to have a special translucent value, so that the empty - * surroundings of the smaller image do not occlude the bigger image. - * - * The smallest possible short (-32768) is used for this. Due to the - * implementation of vtkLookupTable, the lookup table needs to be extended - * so that this value is included. Entries between -32768 and the actual - * table minimum will be set to the lowest entry in the input lookup table. - * From this point onward, the input lookup is just copied into the output - * lookup table. - * - * See also mitk::ImageMapperGL2D, where -32768 is defined as BackgroundLevel - * for resampling. - * - * NOTE: This method is currently not used; to make sure that the plane is - * not rendered with translucent "holes", a black background plane is first - * rendered under all other planes. - */ - //virtual void BuildPaddedLookupTable( - // vtkLookupTable *inputLookupTable, vtkLookupTable *outputLookupTable, - // vtkFloatingPointType min, vtkFloatingPointType max ); - - int FindPowerOfTwo( int i ); - 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; - /** \brief Whether or not to display normals */ - bool m_DisplayNormals; - - /** \brief Whether to color front and back */ - bool m_ColorTwoSides; - - /** \brief Whether or not to invert normals */ - bool m_InvertNormals; - /** 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; 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 > 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 */