diff --git a/Core/Code/Rendering/mitkGLMapper.cpp b/Core/Code/Rendering/mitkGLMapper.cpp index 367b15e79b..58754465ce 100644 --- a/Core/Code/Rendering/mitkGLMapper.cpp +++ b/Core/Code/Rendering/mitkGLMapper.cpp @@ -1,49 +1,49 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGL.h" #include "mitkGLMapper.h" mitk::GLMapper::GLMapper() { } mitk::GLMapper::~GLMapper() { } -void mitk::GLMapper::MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type){ +void mitk::GLMapper::MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType /* type */){ if(IsVisible(renderer)==false) return; Paint(renderer); } void mitk::GLMapper::ApplyProperties(mitk::BaseRenderer* renderer) { float rgba[4]={1.0f,1.0f,1.0f,1.0f}; // check for color prop and use it for rendering if it exists GetColor(rgba, renderer); // check for opacity prop and use it for rendering if it exists GetOpacity(rgba[3], renderer); glColor4fv(rgba); } diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp index 1f8b7b1fde..4d1c1e1bbc 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp @@ -1,664 +1,664 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #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" #include "mitkResliceMethodProperty.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::GenerateDataForRenderer(mitk::BaseRenderer* renderer) +void mitk::Geometry2DDataMapper2D::GenerateDataForRenderer(mitk::BaseRenderer* /* renderer */) { // 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 > mainLine, otherLine; Line< ScalarType, 2 > primaryHelperLine, secondaryHelperLine; mainLine.SetPoints( lineFrom, lineTo ); primaryHelperLine.SetPoints( lineFrom, lineTo ); secondaryHelperLine.SetPoints( lineFrom, lineTo ); displayGeometry->WorldToDisplay( lineFrom, lineFrom ); displayGeometry->WorldToDisplay( lineTo, lineTo ); ScalarType lengthInDisplayUnits = (lineTo - lineFrom).GetNorm(); Vector2D mainLineDirectionOrthogonal; mainLineDirectionOrthogonal[0] = -mainLine.GetDirection()[1]; mainLineDirectionOrthogonal[1] = mainLine.GetDirection()[0]; // 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 > mainLineParams; std::vector< ScalarType > primaryHelperLineParams; std::vector< ScalarType > secondaryHelperLineParams; mainLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); mainLineParams.push_back( 0.0 ); mainLineParams.push_back( 1.0 ); primaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); primaryHelperLineParams.push_back( 0.0 ); primaryHelperLineParams.push_back( 1.0 ); secondaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); secondaryHelperLineParams.push_back( 0.0 ); secondaryHelperLineParams.push_back( 1.0 ); // 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(); //int mainLineThickSlicesMode = 0; int mainLineThickSlicesNum = 1; DataNode* dataNodeOfInputPlaneGeometry = NULL; // Now we have to find the DataNode that contains the inputPlaneGeometry // in order to determine the state of the thick-slice rendering while ( otherPlanesIt != otherPlanesEnd ) { PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >( static_cast< Geometry2DData * >( (*otherPlanesIt)->GetData() )->GetGeometry2D() ); // if we have found the correct node if ( (otherPlane == inputPlaneGeometry) && worldPlaneGeometry->IntersectionLine( otherPlane, otherCrossLine ) ) { dataNodeOfInputPlaneGeometry = (*otherPlanesIt); // if( dataNodeOfInputPlaneGeometry ) // { // mainLineThickSlicesMode = this->DetermineThickSliceMode(dataNodeOfInputPlaneGeometry, mainLineThickSlicesNum); // } break; } otherPlanesIt++; } // if we did not find a dataNode for the inputPlaneGeometry there is nothing we can do from here if ( dataNodeOfInputPlaneGeometry == NULL ) return; // Determine if we should draw the area covered by the thick slicing, default is false. // This will also show the area of slices that do not have thick slice mode enabled bool showAreaOfThickSlicing = false; dataNodeOfInputPlaneGeometry->GetBoolProperty( "reslice.thickslices.showarea", showAreaOfThickSlicing ); // get the normal of the inputPlaneGeometry Vector3D normal = inputPlaneGeometry->GetNormal(); // determine the pixelSpacing in that direction double thickSliceDistance = SlicedGeometry3D::CalculateSpacing( referenceGeometry->GetSpacing(), normal ); // As the inputPlaneGeometry cuts through the center of the slice in the middle // we have to add 0.5 pixel in order to compensate. thickSliceDistance *= mainLineThickSlicesNum+0.5; // not the nicest place to do it, but we have the width of the visible bloc in MM here // so we store it in this fancy property dataNodeOfInputPlaneGeometry->SetFloatProperty( "reslice.thickslices.sizeinmm", thickSliceDistance*2 ); if ( showAreaOfThickSlicing ) { // vectorToHelperLine defines how to reach the helperLine from the mainLine Vector2D vectorToHelperLine; vectorToHelperLine = mainLineDirectionOrthogonal; vectorToHelperLine.Normalize(); // got the right direction, so we multiply the width vectorToHelperLine *= thickSliceDistance; // and create the corresponding points primaryHelperLine.SetPoints( primaryHelperLine.GetPoint1() - vectorToHelperLine, primaryHelperLine.GetPoint2() - vectorToHelperLine ); secondaryHelperLine.SetPoints( secondaryHelperLine.GetPoint1() + vectorToHelperLine, secondaryHelperLine.GetPoint2() + vectorToHelperLine ); } //int otherLineThickSlicesMode = 0; int otherLineThickSlicesNum = 1; // by default, there is no gap for the helper lines ScalarType gapSize = 0.0; otherPlanesIt = m_OtherGeometry2Ds.begin(); while ( otherPlanesIt != otherPlanesEnd ) { PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >( static_cast< Geometry2DData * >( (*otherPlanesIt)->GetData() )->GetGeometry2D() ); // Just as with the original line, calculate the intersection with // the world geometry... if ( (otherPlane != inputPlaneGeometry) && worldPlaneGeometry->IntersectionLine( otherPlane, otherCrossLine ) ) { //otherLineThickSlicesMode = this->DetermineThickSliceMode((*otherPlanesIt), otherLineThickSlicesNum); Vector3D normal = otherPlane->GetNormal(); double otherLineThickSliceDistance = SlicedGeometry3D::CalculateSpacing( referenceGeometry->GetSpacing(), normal ); otherLineThickSliceDistance *= (otherLineThickSlicesNum+0.5)*2; Point2D otherLineFrom, otherLineTo; // ... 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 ), otherLineFrom ); worldPlaneGeometry->Map( transform->TransformPoint( point2 ), otherLineTo ); otherLine.SetPoints( otherLineFrom, otherLineTo ); // then we have to determine the gap position of the main line // by finding the position at which the two lines cross this->DetermineParametricCrossPositions( mainLine, otherLine, mainLineParams ); // if the other line is also in thick slice mode, we have to determine the // gapsize considering the width of that other line and the spacing in its direction if ( showAreaOfThickSlicing ) { Vector2D otherLineDirection = otherLine.GetDirection(); otherLineDirection.Normalize(); mainLineDirectionOrthogonal.Normalize(); // determine the gapsize gapSize = fabs( otherLineThickSliceDistance / ( otherLineDirection*mainLineDirectionOrthogonal ) ); gapSize = gapSize / displayGeometry->GetScaleFactorMMPerDisplayUnit(); // determine the gap positions for the helper lines as well this->DetermineParametricCrossPositions( primaryHelperLine, otherLine, primaryHelperLineParams ); this->DetermineParametricCrossPositions( secondaryHelperLine, otherLine, secondaryHelperLineParams ); } } } ++otherPlanesIt; } // If we have to draw the helperlines, the mainline will be drawn as a dashed line // with a fixed gapsize of 10 pixels this->DrawLine(renderer, lengthInDisplayUnits, mainLine, mainLineParams, inputPlaneGeometry, showAreaOfThickSlicing, 10.0 ); // If drawn, the helperlines are drawn as a solid line. The gapsize depends on the // width of the crossed line. if ( showAreaOfThickSlicing ) { this->DrawLine(renderer, lengthInDisplayUnits, primaryHelperLine, primaryHelperLineParams, inputPlaneGeometry, false, gapSize ); this->DrawLine(renderer, lengthInDisplayUnits, secondaryHelperLine, secondaryHelperLineParams, inputPlaneGeometry, false, gapSize ); } } } } 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; } } void mitk::Geometry2DDataMapper2D::DrawLine( BaseRenderer* renderer, ScalarType lengthInDisplayUnits, Line &line, std::vector &gapPositions, const PlaneGeometry* inputPlaneGeometry, bool drawDashed, ScalarType gapSizeInPixel ) { DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); const PlaneGeometry *worldPlaneGeometry = dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldGeometry2D() ); // Apply color and opacity read from the PropertyList. this->ApplyProperties( renderer ); ScalarType gapSizeInParamUnits = 1.0 / lengthInDisplayUnits * gapSizeInPixel; std::sort( gapPositions.begin(), gapPositions.end() ); Point2D p1, p2; ScalarType p1Param, p2Param; p1Param = gapPositions[0]; p1 = line.GetPoint( p1Param ); displayGeometry->WorldToDisplay( p1, p1 ); //Workaround 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; if ( drawDashed ) { glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0xF0F0); } glEnable(GL_DEPTH_TEST); // Iterate over all line segments and display each, with a gap // in between. unsigned int i, preLastLineParam = gapPositions.size() - 1; for ( i = 1; i < preLastLineParam; ++i ) { p2Param = gapPositions[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 glBegin (GL_LINES); 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 = gapPositions[i]; p2 = line.GetPoint( p2Param ); displayGeometry->WorldToDisplay( p2, p2 ); glBegin( GL_LINES ); glVertex3f( p1[0], p1[1], depthPosition); glVertex3f( p2[0], p2[1], depthPosition); glEnd(); if ( drawDashed ) { glDisable(GL_LINE_STIPPLE); } // 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 ); } } } int mitk::Geometry2DDataMapper2D::DetermineThickSliceMode( DataNode * dn, int &thickSlicesNum ) { int thickSlicesMode = 0; // determine the state and the extend of the thick-slice mode mitk::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=0; if(thickSlicesNum > 10) thickSlicesNum=10; } if ( thickSlicesMode == 0 ) thickSlicesNum = 0; return thickSlicesMode; } void mitk::Geometry2DDataMapper2D::DetermineParametricCrossPositions( Line< mitk::ScalarType, 2 > &mainLine, Line< mitk::ScalarType, 2 > &otherLine, std::vector< mitk::ScalarType > &crossPositions ) { Vector2D direction, dOrth; // By means of the dot product, calculate the gap position as // parametric value in the range [0, 1] direction = otherLine.GetDirection(); dOrth[0] = -direction[1]; dOrth[1] = direction[0]; ScalarType gapPosition = ( otherLine.GetPoint1() - mainLine.GetPoint1() ) * dOrth; ScalarType norm = mainLine.GetDirection() * dOrth; if ( fabs( norm ) > eps ) { gapPosition /= norm; if ( (gapPosition > 0.0) && (gapPosition < 1.0) ) { crossPositions.push_back(gapPosition); } } } diff --git a/Core/Code/Rendering/mitkMapper.h b/Core/Code/Rendering/mitkMapper.h index 3c7a3edb8e..27a51f6906 100644 --- a/Core/Code/Rendering/mitkMapper.h +++ b/Core/Code/Rendering/mitkMapper.h @@ -1,279 +1,279 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MAPPER_H_HEADER_INCLUDED_C1E6EA08 #define MAPPER_H_HEADER_INCLUDED_C1E6EA08 #include #include "mitkBaseRenderer.h" #include "mitkVtkPropRenderer.h" #include "mitkLevelWindow.h" #include #include //Just included to get VTK version #include class vtkWindow; class vtkProp; namespace mitk { class BaseRenderer; class BaseData; class DataNode; /** \brief Interface for accessing (templated) LocalStorageHandler instances. */ class BaseLocalStorageHandler { public: virtual ~BaseLocalStorageHandler() {} virtual void ClearLocalStorage(mitk::BaseRenderer *renderer,bool unregisterFromBaseRenderer=true )=0; }; /** \brief Base class of all mappers, Vtk as well as OpenGL mappers * * By the help of mappers, the input data is transformed to tangible primitives, * such as surfaces, points, lines, etc. * This is the base class of all mappers, Vtk as well as OpenGL mappers. * Subclasses of mitk::Mapper control the creation of rendering primitives * that interface to the graphics library (e.g., OpenGL, vtk). * * \todo Should Mapper be a subclass of ImageSource? * \ingroup Mapper */ class MITK_CORE_EXPORT Mapper : public itk::Object { public: mitkClassMacro(Mapper, itk::Object); /** \brief Set the DataNode containing the data to map */ itkSetObjectMacro(DataNode, DataNode); /**\brief Get the data to map * * Returns the mitk::BaseData object associated with this mapper. * \return the mitk::BaseData associated with this mapper. */ BaseData* GetData() const; /** \brief Get the DataNode containing the data to map */ virtual DataNode* GetDataNode() const; /** \brief Convenience access method for color properties (instances of * ColorProperty) * \return \a true property was found */ virtual bool GetColor(float rgb[3], BaseRenderer* renderer, const char* name = "color") const; /** \brief Convenience access method for visibility properties (instances * of BoolProperty) * \return \a true property was found * \sa IsVisible */ virtual bool GetVisibility(bool &visible, BaseRenderer* renderer, const char* name = "visible") const; /** \brief Convenience access method for opacity properties (instances of * FloatProperty) * \return \a true property was found */ virtual bool GetOpacity(float &opacity, BaseRenderer* renderer, const char* name = "opacity") const; /** \brief Convenience access method for color properties (instances of * LevelWindoProperty) * \return \a true property was found */ virtual bool GetLevelWindow(LevelWindow &levelWindow, BaseRenderer* renderer, const char* name = "levelwindow") const; /** \brief Convenience access method for visibility properties (instances * of BoolProperty). Return value is the visibility. Default is * visible==true, i.e., true is returned even if the property (\a * propertyKey) is not found. * * Thus, the return value has a different meaning than in the * GetVisibility method! * \sa GetVisibility */ virtual bool IsVisible(BaseRenderer* renderer, const char* name = "visible") const; /** \brief Calls the time step of the input data for the specified renderer and checks * whether the time step is valid and calls method GenerateDataForRenderer() */ virtual void Update(BaseRenderer* renderer); /** \brief Responsible for calling the appropriate render functions. * To be implemented in sub-classes. */ virtual void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type) = 0; /** \brief Returns whether this is an vtk-based mapper */ virtual bool IsVtkBased() const = 0; /** \brief Returns true if this mapper owns the specified vtkProp for * the given BaseRenderer. * * Note: returns false by default; should be implemented for VTK-based * mapper subclasses. */ virtual bool HasVtkProp( const vtkProp* /*prop*/, BaseRenderer* /*renderer*/ ){ return false; }; // virtual bool IsPickable() const = 0; /** * \brief Release vtk-based graphics resources. Must be overwritten in * subclasses if vtkProps are used. */ virtual void ReleaseGraphicsResources(vtkWindow*) { }; /** \brief Set default values of properties used by this mapper * to \a node * * \param node The node for which the properties are set * \param overwrite overwrite existing properties (default: \a false) * \param renderer defines which property list of node is used * (default: \a NULL, i.e. default property list) */ static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief Returns the current time step as calculated from the renderer */ int GetTimestep() const { return m_TimeStep; }; /** Returns true if this Mapper currently allows for Level-of-Detail rendering. * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and * ProgressEvent on BaseRenderer. */ virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return false; } protected: Mapper(); virtual ~Mapper(); /** \brief Generate the data needed for rendering (independent of a specific renderer) */ virtual void GenerateData() { }; /** \brief Generate the data needed for rendering into \a renderer */ - virtual void GenerateDataForRenderer(BaseRenderer* renderer) { }; + virtual void GenerateDataForRenderer(BaseRenderer* /* renderer */) { }; /** \brief Updates the time step, which is sometimes needed in subclasses */ virtual void CalculateTimeStep( BaseRenderer* renderer ); /** \brief Reset the mapper (i.e., make sure that nothing is displayed) if no * valid data is present. * To be implemented in sub-classes. */ virtual void ResetMapper( BaseRenderer* /*renderer*/ ) { }; itk::WeakPointer m_DataNode; /** \brief timestamp of last update of stored data */ itk::TimeStamp m_LastUpdateTime; private: /** \brief The current time step of the dataset to be rendered, * for use in subclasses. * The current timestep can be accessed via the GetTimestep() method. */ int m_TimeStep; public: /** \brief Base class for mapper specific rendering ressources. */ class BaseLocalStorage { }; /** \brief Templated class for management of LocalStorage implementations in Mappers. * * The LocalStorageHandler is responsible for providing a LocalStorage to a * concrete mitk::Mapper subclass. Each RenderWindow / mitk::BaseRenderer is * assigned its own LocalStorage instance so that all contained ressources * (actors, shaders, textures, ...) are provided individually per window. * */ template class LocalStorageHandler : public mitk::BaseLocalStorageHandler { protected: std::map m_BaseRenderer2LS; public: /** \brief deallocates a local storage for a specifc BaseRenderer (if the * BaseRenderer is itself deallocating it in its destructor, it has to set * unregisterFromBaseRenderer=false) */ virtual void ClearLocalStorage(mitk::BaseRenderer *renderer,bool unregisterFromBaseRenderer=true ) { //MITK_INFO << "deleting a localstorage on a mapper request"; if(unregisterFromBaseRenderer) renderer->UnregisterLocalStorageHandler( this ); L *l = m_BaseRenderer2LS[renderer]; m_BaseRenderer2LS.erase( renderer ); delete l; } /** \brief Retrieves a LocalStorage for a specific BaseRenderer. * * Should be used by mappers in GenerateData() and ApplyProperties() */ L *GetLocalStorage(mitk::BaseRenderer *forRenderer) { L *l = m_BaseRenderer2LS[ forRenderer ]; if(!l) { //MITK_INFO << "creating new localstorage"; l = new L; m_BaseRenderer2LS[ forRenderer ] = l; forRenderer->RegisterLocalStorageHandler( this ); } return l; } ~LocalStorageHandler() { typename std::map::iterator it; for ( it=m_BaseRenderer2LS.begin() ; it != m_BaseRenderer2LS.end(); it++ ) { (*it).first->UnregisterLocalStorageHandler(this); delete (*it).second; } m_BaseRenderer2LS.clear(); } }; }; } // namespace mitk #endif /* MAPPER_H_HEADER_INCLUDED_C1E6EA08 */